译码器 位运算 点阵
回帖(1)
2022-2-25 11:22:59
void DigDisplay()
{
u8 i;
for(i=0;i<8;i++)
{
switch(i) //位选,选择点亮的数码管,
{
case(0):
LSA=0;LSB=0;LSC=0; break;//显示第0位
case(1):
LSA=1;LSB=0;LSC=0; break;//显示第1位
case(2):
LSA=0;LSB=1;LSC=0; break;//显示第2位
case(3):
LSA=1;LSB=1;LSC=0; break;//显示第3位
case(4):
LSA=0;LSB=0;LSC=1; break;//显示第4位
case(5):
LSA=1;LSB=0;LSC=1; break;//显示第5位
case(6):
LSA=0;LSB=1;LSC=1; break;//显示第6位
case(7):
LSA=1;LSB=1;LSC=1; break;//显示第7位
}
P0=smgduan;//发送段码
delay(100); //间隔一段时间扫描
P0=0x00;//消隐
}
}
可以看出,为了驱动138译码器,使用了switch语句,占用了较多空间,并不算太简洁,对内存小的单片机也不友好。
因此,可以使用位操作以简化。如下的点阵扫描函数
//138驱动 从左向右发送扫描信号
void sendLine138(u16 dat)
{
Y1382 = dat % 2;
Y1381 = (dat >> 1) % 2;
Y1380 = (dat >> 2) % 2;
}
如想输出 1111 1101 ,即第七个输出端为低电位,其他为高电位
输入参数为 7 二进制 0111
7%2=1
7>>1 = 0011 = 3 3%2=1
7>>2 = 0001 = 2 2%2=0
明显的,可以找出如函数中所示规律
由于位运算非常高效,所以用这个方法可以大幅提高效率,特别是大程序中。
但需要一定的经验才能快速判断出需要用什么样的位运算
- 整体发送防止频闪
有时候我们需要并联芯片以操作多个元器件,以4个595芯片级联控制4个led点阵为例,以下为局部代码,效果是发送每行扫描的数据
//发送的数据 0
u8 l[8] = {0x83,0xBB,0xBB,0xBB,0xBB,0xBB,0xBB,0x83};
///595数据发送函数
void sendCol595(u8 dat)
{
char i;
for (i = 0; i < 8; i++) //连续重复八次,发送8位数据
{
SER = (dat >> i) % 2;
SCK = 0;
SCK = 1;
}
}
//主函数中
GOUT = 0;
while (1)
{
for ( i = 0; i < 8; i++)
{
sendCol595(l);
sendCol595(l);
sendCol595(l);
sendCol595(l); //这里发送,每个单独发送需要一定的处理时间,故导致下面发GOUT开关不能及时生效,导致频闪
RCK = 0;
RCK = 1;
GOUT = 1;
GOUT = 0;
}
}
有一种新的思路,将595传到的数据临时保存在寄存器中,等到四个595中的数据全部接受完成,RCK跳一下,统一发送,频闪基本消失,如代码
```c
//发送的数据 0
u8 l[8] = {0x83,0xBB,0xBB,0xBB,0xBB,0xBB,0xBB,0x83};
///595数据发送函数
void sendCol595(u8 dat)
{
char i;
for (i = 0; i < 8; i++) //连续重复八次,发送8位数据
{
SER = (dat >> i) % 2;
SCK = 0;
SCK = 1;
}
// 这里将RCK放在后面统一控制
}
//主函数中
GOUT = 0;
while (1)
{
for ( i = 0; i < 8; i++)
{
sendCol595(l);
sendCol595(l);
sendCol595(l);
sendCol595(l);
RCK = 0; //数据接受完成,统一发送
RCK = 1;
GOUT = 1;
GOUT = 0;
}
}
void DigDisplay()
{
u8 i;
for(i=0;i<8;i++)
{
switch(i) //位选,选择点亮的数码管,
{
case(0):
LSA=0;LSB=0;LSC=0; break;//显示第0位
case(1):
LSA=1;LSB=0;LSC=0; break;//显示第1位
case(2):
LSA=0;LSB=1;LSC=0; break;//显示第2位
case(3):
LSA=1;LSB=1;LSC=0; break;//显示第3位
case(4):
LSA=0;LSB=0;LSC=1; break;//显示第4位
case(5):
LSA=1;LSB=0;LSC=1; break;//显示第5位
case(6):
LSA=0;LSB=1;LSC=1; break;//显示第6位
case(7):
LSA=1;LSB=1;LSC=1; break;//显示第7位
}
P0=smgduan;//发送段码
delay(100); //间隔一段时间扫描
P0=0x00;//消隐
}
}
可以看出,为了驱动138译码器,使用了switch语句,占用了较多空间,并不算太简洁,对内存小的单片机也不友好。
因此,可以使用位操作以简化。如下的点阵扫描函数
//138驱动 从左向右发送扫描信号
void sendLine138(u16 dat)
{
Y1382 = dat % 2;
Y1381 = (dat >> 1) % 2;
Y1380 = (dat >> 2) % 2;
}
如想输出 1111 1101 ,即第七个输出端为低电位,其他为高电位
输入参数为 7 二进制 0111
7%2=1
7>>1 = 0011 = 3 3%2=1
7>>2 = 0001 = 2 2%2=0
明显的,可以找出如函数中所示规律
由于位运算非常高效,所以用这个方法可以大幅提高效率,特别是大程序中。
但需要一定的经验才能快速判断出需要用什么样的位运算
- 整体发送防止频闪
有时候我们需要并联芯片以操作多个元器件,以4个595芯片级联控制4个led点阵为例,以下为局部代码,效果是发送每行扫描的数据
//发送的数据 0
u8 l[8] = {0x83,0xBB,0xBB,0xBB,0xBB,0xBB,0xBB,0x83};
///595数据发送函数
void sendCol595(u8 dat)
{
char i;
for (i = 0; i < 8; i++) //连续重复八次,发送8位数据
{
SER = (dat >> i) % 2;
SCK = 0;
SCK = 1;
}
}
//主函数中
GOUT = 0;
while (1)
{
for ( i = 0; i < 8; i++)
{
sendCol595(l);
sendCol595(l);
sendCol595(l);
sendCol595(l); //这里发送,每个单独发送需要一定的处理时间,故导致下面发GOUT开关不能及时生效,导致频闪
RCK = 0;
RCK = 1;
GOUT = 1;
GOUT = 0;
}
}
有一种新的思路,将595传到的数据临时保存在寄存器中,等到四个595中的数据全部接受完成,RCK跳一下,统一发送,频闪基本消失,如代码
```c
//发送的数据 0
u8 l[8] = {0x83,0xBB,0xBB,0xBB,0xBB,0xBB,0xBB,0x83};
///595数据发送函数
void sendCol595(u8 dat)
{
char i;
for (i = 0; i < 8; i++) //连续重复八次,发送8位数据
{
SER = (dat >> i) % 2;
SCK = 0;
SCK = 1;
}
// 这里将RCK放在后面统一控制
}
//主函数中
GOUT = 0;
while (1)
{
for ( i = 0; i < 8; i++)
{
sendCol595(l);
sendCol595(l);
sendCol595(l);
sendCol595(l);
RCK = 0; //数据接受完成,统一发送
RCK = 1;
GOUT = 1;
GOUT = 0;
}
}
举报
更多回帖