一、遇到的问题
还记得我前面在封装继电器外设的时候遇到的这个问题嘛,当时我怀疑的是138译码器在切换通道的时候会出现其他暂态导致已经锁定的573解锁。
其实不然,之所以会这样还是因为代码问题,也可以说是573反应时间太快了。下面我就分析一下为什么会这样!
二、问题分析
假设我们要先操作LED,再操作继电器,那么按照我之前的写法会是这样:先写001解锁LED,再写000锁存。然后写101解锁继电器,再写000锁存。好,问题就出在最后一步,当P25=0时,P26还等于0,P27还等于1,这个短暂的瞬间组成了001刚好就会解锁LED。所以这就是为什么我当时用110去锁存继电器就不会解锁LED了。
总结一下就是:在操作138去解锁锁存573的时候一定要用整个IO端口操作,不能像我这样图简单方便用单独位操作!
正确写法:
void select_573(u8 x)
{
if(x==0) P2 &=0x1F; //锁存
else if(x==4) P2 |=0x80; //解锁LED所在573
else if(x==5) P2 |=0xA0; //解锁继电器所在573
else if(x==6) P2 |=0xC0; //解锁数码管位码所在573
else if(x==7) P2 |=0xE0; //解锁数码管段码所在573
else;
//踩坑提示:一定要采用整个端口操作,不能单独位操作!!!
}
u8 Led_Status=0xFF; //初始关闭
void Set_Led(unsigned char Leds)
{
//选中LED所在573,此时输出跟随输入变化
select_573(4); //74HC138-->Y4=0,else=1-->Y4C=1,else=0
P0=Leds;
Led_Status=Leds; //记录LED状态
//锁存LED所在573
select_573(0); //74HC138-->Y1=0,else=1
}
/**********Set_Leds**************
* location: operate which led
* status:1 ON,0 OFF
********************************/
void Set_Leds(u8 location,u8 status)
{
//选中LED所在573,此时输出跟随输入变化
select_573(4); //74HC138-->Y4=0,else=1-->Y4C=1,else=0
P0 = Led_Status; //防止解锁时LED状态改变
P0 |= 0x01<<(location-1); //清除对应位
P0 &= ~(status <<(location-1)); //设置对应位
Led_Status=P0; //记录所有LED灯状态
//锁存LED所在573
select_573(0); //74HC138-->Y1=0,else=1
}