一些单片机学习的收获存档1

  • 关于位运算简化代码的思路(138译码器为例子)

原始代码:


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[i];//发送段码
        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[i]);
            sendCol595(l[i]);
            sendCol595(l[i]);
            sendCol595(l[i]); //这里发送,每个单独发送需要一定的处理时间,故导致下面发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[i]);
            sendCol595(l[i]);
            sendCol595(l[i]);
            sendCol595(l[i]); 
            RCK = 0; //数据接受完成,统一发送
        	RCK = 1;
            GOUT = 1;
            GOUT = 0;
        }

    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值