1 Star 3 Fork 1

sjzc-qwz/dled_ctl

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
dled_ctl.c 5.68 KB
一键复制 编辑 原始数据 按行查看 历史
Nixsawe 提交于 2022-01-03 21:48 . 修复显示 bug,并添加一些注释
/**
* dled_ctl.c - 动态数码管控制库 (3461AS-1)
* by Nixsawe <ziming_cool@126.com>
* 2021-11-12 ~ 2021-12-17
*
* 为了更方便地使用 3461AS-1 数码管,特封装此库
* 包含如下函数:
* void dledShowDP(DLED_T byte, DLED_T dp, DLED_T pos);
* void dledShow(DLED_T byte, DLED_T pos);
* void dledShowBytes(DLED_T * a, int start_pos, int length);
* void dledShowDigits(DLED_T * a, int start_pos, int length);
* void dledFormat(long number, DLED_T * a, int length);
* void dledShowNumber(long number, int show_prefix);
* void dledMakeBuffer(long number, int show_prefix);
* void dledShowBuffer();
* void dledSetAll();
* void dledClear();
*
* 注意,本库中所使用的位置索引,与数码管实际的位置索引是相反的。
* 数码管实际索引顺序为从右到左,本库中索引顺序为从左到右。
* 故在本库中 pos=0 代表左数第一组数码管,这样更符合我们的思考方式。
*
* 在使用时,将 dled_ctl.c 添加到工程中,
* 并将文件所在目录添加到工程的包含目录列表,
* 然后在要使用本功能的源文件中引用头文件 dled_ctl.h
*/
#include "dled_ctl.h"
#ifdef DLED_PCTL_USE_BYTE_REGISTER
sfr DLED_PCTL = DLED_PCTL_ADDR;
#endif
// 定义数组以存放数字的字节码
DLED_T dled_digit[10] = {
DLED_DIGIT_0,
DLED_DIGIT_1,
DLED_DIGIT_2,
DLED_DIGIT_3,
DLED_DIGIT_4,
DLED_DIGIT_5,
DLED_DIGIT_6,
DLED_DIGIT_7,
DLED_DIGIT_8,
DLED_DIGIT_9
};
// 缓冲区
DLED_T dled_buffer[8];
/**
* 点亮一组数码管,小数点单独指定
*/
void dledShowDP(DLED_T byte, DLED_T dp, DLED_T pos)
{
dledShow(DLED_BYTE_DP(byte, dp), pos);
}
/**
* 点亮一组数码管
* pos 为对应的位置,pos 0-7 对应左到右的 8 组数码管
*/
void dledShow(DLED_T byte, DLED_T pos)
{
// 清除所有位 (这是为了在移动偏移位置时不会导致“残像”)
DLED_ADDR = 0;
// 设置偏移位置
# ifdef DLED_PCTL_USE_BYTE_REGISTER
DLED_PCTL = pos;
# else
DLED_PCTL_A = !(pos & 1);
DLED_PCTL_B = !(pos & 2);
DLED_PCTL_C = !(pos & 4);
# endif
// 点亮对应的位
DLED_ADDR = byte;
}
/**
* 点亮所有数码管
* 第一个参数,接受一个有 8 个元素的数组,第二个参数为开始位置,第三个参数为数组长度
* 本函数接受的数组,其元素为转换好的数码管字节码
*/
void dledShowBytes(DLED_T * a, int start_pos, int length)
{
int i, right = DLED_MIN(length, 8 - start_pos);
for(i = right - 1; i >= 0; i --)
{
dledShow(a[i], start_pos + i);
}
}
/**
* 点亮所有数码管
* 第一个参数,接受一个有 8 个数字的数组,第二个参数为开始位置,第三个参数为数组长度
* 本函数接受的数组,其元素为数字,本函数会将其自动转换成数码管字节码
*/
void dledShowDigits(DLED_T * a, int start_pos, int length)
{
int i, right = DLED_MIN(length, 8 - start_pos);
for(i = right - 1; i >= 0; i --)
{
dledShow(dled_digit[a[i]], start_pos + i);
}
}
/**
* 格式化字节码
* 第一个参数,接受一个数字(不超过 8 位 10 进制数),第二个参数为目标数组,第三个参数为数组长度
* 本函数会将其自动转换成数码管字节码,置于 a 的最后几个字节中
* 如果 a 长度不足以放下数字或数字超过可表示范围,则 a 被清零,最后一个字节置一个负号的字节码
*/
void dledFormat(long num, DLED_T * a, int length)
{
int len = 0, i, neg = 0;
do
{
if(num > 99999999 || num < -9999999)
break;
if(num < 0)
{
num = -num;
neg = 1;
}
for(i = 0; i < 8; i ++)
{
if(++ len > length)
break;
a[length - i - 1] = dled_digit[num % 10];
num /= 10;
if(!num) break;
}
if(num)
break;
if(neg)
{
if(len >= length)
break;
a[length - i - 1] = DLED_DIGIT_MINUS;
len ++;
}
if(len < length)
{
memset(a, 0, sizeof(DLED_T) * (length - len));
}
return;
} while(0);
if(length > 0)
{
memset(a, 0, sizeof(DLED_T) * length);
a[length - 1] = DLED_DIGIT_MINUS;
}
}
/**
* 点亮所有数码管
* 第一个参数,接受一个八位数(数显管最多显示 8 位,十进制),第二个参数为 1 代表显示前缀 0,为 0 则不显示
* 会变缓冲区内容
*/
void dledShowNumber(long number, int show_prefix)
{
// 根据参数准备缓冲区内容
dledMakeBuffer(number, show_prefix);
// 将缓冲区内容打印出来
dledShowBuffer();
}
/**
* 预点亮所有数码管
* 这个函数并不会实际点亮数码管,它仅仅构造好对应的缓冲区,可用 dledShowBuffer 直接进行点亮
* 直接根据数字计算数码管字节码的速度很慢(单片机主频比较低),用这种方法可以进行优化
* 会变缓冲区内容
*/
void dledMakeBuffer(long number, int show_prefix)
{
int i, neg = 0;
if(number > 99999999 || number < -9999999)
{
// 当前精度不足以显示所有位数
memset(dled_buffer, DLED_DIGIT_MINUS, sizeof(dled_buffer));
return;
}
if(number < 0)
{
number = -number;
neg = 1;
}
for(i = 7; i >= 0; i --)
{
dled_buffer[i] = dled_digit[number % 10];
number /= 10;
if(!number && !show_prefix)
{
i --;
break;
}
}
if(neg)
{
dled_buffer[i >= 0 ? i : 0] = DLED_DIGIT_MINUS;
i --;
}
if(i >= 0) memset(dled_buffer, 0, sizeof(DLED_T) * (i + 1));
}
/**
* 使用缓冲区的数据点亮所有数码管
*/
void dledShowBuffer()
{
dledShowBytes(dled_buffer, 0, 8);
}
/**
* 点亮所有数码管的所有位
* 会变缓冲区内容
*/
void dledSetAll()
{
unsigned char byte = -1u;
memset(dled_buffer, byte, sizeof(dled_buffer));
dledShowBuffer();
}
/**
* 清空所有数码管的所有位
* 会变缓冲区内容
*/
void dledClear()
{
memset(dled_buffer, 0, sizeof(dled_buffer));
dledShow(0, 0);
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C
1
https://gitee.com/sjzc-qwz/dled_ctl.git
git@gitee.com:sjzc-qwz/dled_ctl.git
sjzc-qwz
dled_ctl
dled_ctl
master

搜索帮助