找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1986|回复: 19
收起左侧

请教一下单片机IO口复用驱动数码管时如何避免冲突?

  [复制链接]
ID:734017 发表于 2022-4-11 21:08 | 显示全部楼层 |阅读模式
51hei截图_20220411205056.png 51hei截图_20220411205021.png
如上图的单片机电路图,用26个IO 复用驱动6个数码管,21个LDE ,18个按键。、
个人理解按键那里会与段选冲突。
比喻在一个1MS的周期内,P44位选给1.段选全部给0.数码管显示8.
如果在这个周期里,P46给的是1,当按下Key1的时候,F段理论上灭掉
情况2  周期内位选 P44给1,段选全给1 。P46给0.当按下key1时,F段理论会亮


回复

使用道具 举报

ID:401564 发表于 2022-4-11 21:48 | 显示全部楼层
一个数字的数码,com是短路的,接一个就行了,不用接两个引脚的
6个数码管只会用到8+6=14个引脚
不知道你是怎么用到26个IO的?
这么多的按键,为什么不用ADC
四多的STC8A8K有59个IO和上拉电阻,为什么不用?
回复

使用道具 举报

ID:734017 发表于 2022-4-11 21:51 | 显示全部楼层
Y_G_G 发表于 2022-4-11 21:48
一个数字的数码,com是短路的,接一个就行了,不用接两个引脚的
6个数码管只会用到8+6=14个引脚
不知道你是 ...

15年的产品了,库存货想自己改掉。原理图是对着画的
回复

使用道具 举报

ID:734017 发表于 2022-4-11 21:53 | 显示全部楼层
Y_G_G 发表于 2022-4-11 21:48
一个数字的数码,com是短路的,接一个就行了,不用接两个引脚的
6个数码管只会用到8+6=14个引脚
不知道你是 ...

写错了,是6个双位的数码管,
回复

使用道具 举报

ID:624769 发表于 2022-4-11 22:26 | 显示全部楼层
按键复用 接数码管的  位,  不要接数码管的  段。
在点亮某个  位  的数码管时  顺便判断  和该位共用的 按键有没有 被按下即可。
回复

使用道具 举报

ID:824490 发表于 2022-4-11 22:28 | 显示全部楼层
只要软件能做到“分时复用”,没有问题,IO复用多了去了。
回复

使用道具 举报

ID:734017 发表于 2022-4-11 22:53 | 显示全部楼层
188610329 发表于 2022-4-11 22:26
按键复用 接数码管的  位,  不要接数码管的  段。
在点亮某个  位  的数码管时  顺便判断  和该位共用的  ...

我这是共阳的,按你的方法,按下去的时候不是要把 位选拉低吗?那不影响数码管显示吗?方便的话,提供一个图,谢谢
回复

使用道具 举报

ID:624769 发表于 2022-4-11 23:38 | 显示全部楼层
happy2058 发表于 2022-4-11 22:53
我这是共阳的,按你的方法,按下去的时候不是要把 位选拉低吗?那不影响数码管显示吗?方便的话,提供一 ...

共阳的数码管 和 按键复用时  按键检测端的IO 内部寄存器置1,外部通过47K~100K 电阻下拉到地, IO模式设置为高阻或者开漏, 检测 外部电平, 高电平表示按键被按下,低电平表示按键没有被按下。
回复

使用道具 举报

ID:161164 发表于 2022-4-11 23:52 | 显示全部楼层
是2015年的产品还是15年前的产品?
用什么型号的单片机?
有高阻IO设定时吗?
如果有就好办了

显示的时候P46/P13/P15设为高阻
按键就不影响显示

按键扫描时
所有位输出置0
P46/P13/P15设为双向弱上拉并置1
把段输出设为0xFE,并检测P46/P13有没有拉低,有就是key3/key8被按下
把段输出设为0xFD,并检测P46/P13/P15有没有拉低,有就是key5/key14/key18被按下
...
把各段都拉低后还原要显示的段输出,还原位输出,P46/P13/P15设为高阻

回复

使用道具 举报

ID:734017 发表于 2022-4-12 01:04 | 显示全部楼层
188610329 发表于 2022-4-11 23:38
共阳的数码管 和 按键复用时  按键检测端的IO 内部寄存器置1,外部通过47K~100K 电阻下拉到地, IO模式设 ...

嗯,感谢了, 按你的方法,循环时间快。不用单独判断
回复

使用道具 举报

ID:734017 发表于 2022-4-12 01:05 | 显示全部楼层
lkc8210 发表于 2022-4-11 23:52
是2015年的产品还是15年前的产品?
用什么型号的单片机?
有高阻IO设定时吗?

2015的  15W408S 查了手册,IO可选4种态度
回复

使用道具 举报

ID:213173 发表于 2022-4-12 06:59 | 显示全部楼层
happy2058 发表于 2022-4-12 01:05
2015的  15W408S 查了手册,IO可选4种态度

按你现有的条件可以做到用26个IO 复用驱动6个两位数码管,21个LDE ,18个按键。不过电路连接关系要改。把12个数码管看成96个LED,加上21个LDE共117,或看成15个数码管,有15个共用阳极,分别各接一个按键,另3个IO各接一个按键。 无标题.jpg

无标题1.jpg

回复

使用道具 举报

ID:734017 发表于 2022-4-12 09:34 | 显示全部楼层
wulin 发表于 2022-4-12 06:59
按你现有的条件可以做到用26个IO 复用驱动6个两位数码管,21个LDE ,18个按键。不过电路连接关系要改。把1 ...

我有点疑惑,检测的时候,IO电平会拉低,灯不是灭了吗?
回复

使用道具 举报

ID:213173 发表于 2022-4-12 10:14 | 显示全部楼层
happy2058 发表于 2022-4-12 09:34
我有点疑惑,检测的时候,IO电平会拉低,灯不是灭了吗?

检测按键的时候,如有键按下,IO口电平会被拉低,灯是要灭的。但这个过程只有几微秒,你能察觉出来?
回复

使用道具 举报

ID:734017 发表于 2022-4-12 10:30 | 显示全部楼层
wulin 发表于 2022-4-12 10:14
检测按键的时候,如有键按下,IO口电平会被拉低,灯是要灭的。但这个过程只有几微秒,你能察觉出来?

那也是,谢谢了
回复

使用道具 举报

ID:734017 发表于 2022-4-12 10:30 | 显示全部楼层
wulin 发表于 2022-4-12 10:14
检测按键的时候,如有键按下,IO口电平会被拉低,灯是要灭的。但这个过程只有几微秒,你能察觉出来?

长按的时候???一直不亮
回复

使用道具 举报

ID:123289 发表于 2022-4-12 11:28 | 显示全部楼层
在扫描显示的“消隐”期间查键即可。
“消隐”:扫显时,在切换显示值之前,先关显示(让LED的COM失效即可),而后再切换显示内容,这时由于LED已关闭,所以不会产生乱显,之后再打开显示。这段时间就是“消隐”期。
回复

使用道具 举报

ID:213173 发表于 2022-4-12 11:29 | 显示全部楼层
happy2058 发表于 2022-4-12 10:30
长按的时候???一直不亮

这与短按和长按没有任何关系。如果以入门级水平写按键程序就另当别论了。
回复

使用道具 举报

ID:734017 发表于 2022-4-18 22:56 | 显示全部楼层
程序写了一遍,水平有限,请指教  流程上往下,按键扫描从循环数码管输出中插入
bit key_service_Lock=0;                                        //循环标志位,禁止连续扫描       
uchar KeySec = 0;                                                //按键编号       
uchar KeyTimeCnt=0;                                         //按键去抖动延时计数器
uchar key_service_tmp;
while(1)
        {
void Reuse_time_sharing()                                        //复用驱动数码管  此函数通用定时器标位控制,1MS循环一次,每次约15MS
{       
        if(Reuse)
        {       
                Reuse=~Reuse;               
                Reuse_count++;
                                switch(Reuse_count)
                                {
                                        case 1 :                                          //DS1_1        第一个数码管个位
                                                        P05=0;                       //关闭上一个输出位选
                                                        if(!key_service_Lock)  //循环标志位0,进入扫描按键
                                                        key_select();       //扫描按键函数
                                                        P2=Digital_tube_Segment_program_123[Energy_TXD(Ion_B,1)];    //输出段选
                                                        P03=1;       //打开位选
                                                        break;
                                        case 2 :                                         //DS1_10
                                                                P03=0;
                                                                if(!key_service_Lock)
                                                                key_select();
                                                                P2=Digital_tube_Segment_program_123[Energy_TXD(Ion_B,1)];
                                                                P04=1;
                                                                                break;
                                        case 3 :                                         //DS2_1               
                                                                P04=0;
                                                                if(!key_service_Lock)
                                                                key_select();
                                                                P2=Digital_tube_Segment_program_123[Energy_TXD(Ion_B,1)];               
                                                                P02=1;               
                                                                                break;
                                        case 4 :                                         //DS2_10       
                                                                P02=0;
                                                                if(!key_service_Lock)
                                                                key_select();
                                                                P2=Digital_tube_Segment_program_123[Energy_TXD(Ion_B,10)];               
                                                                P47=1;
                                                                                break;
                                        case 5 :                                         //DS3_1       
                                                                P47=0;
                                                                if(!key_service_Lock)
                                                                key_select();
                                                                P2=Digital_tube_Segment_program_123[Energy_TXD(Ion_A,1)];       
                                                                P01=1;
                                                                                break;
                                        case 6 :                                         //DS3_10       
                                                                P01=0;       
                                                                if(!key_service_Lock)
                                                                key_select();
                                                                P2=Digital_tube_Segment_program_123[Energy_TXD(Ion_A,10)];
                                                                P00=1;
                                                                                break;
                                        case 7 :                                         //DS4_1         time
                                                                P00=0;
                                                                if(!key_service_Lock)
                                                                key_select();
                                                                P2=Digital_tube_Segment_program_456[Energy_TXD(Time_MIN,1)];
                                                                P37=1;
                                                                                break;
                                        case 8:                                         //DS4_10        time
                                                                P37=0;
                                                                if(!key_service_Lock)
                                                                key_select();
                                                                P2=Digital_tube_Segment_program_456[Energy_TXD(Time_MIN,10)];
                                                                P41=1;
                                                                                break;
                                        case 9 :                                         //DS5_1               
                                                                P41=0;
                                                                if(!key_service_Lock)
                                                                key_select();
                                                                P2=Digital_tube_Segment_program_456[Energy_TXD(Heat_B,1)];
                                                                P36=1;
                                                                                break;
                                        case 10 :                                        //DS5_10       
                                                                P36=0;
                                                                if(!key_service_Lock)
                                                                key_select();
                                                                P2=Digital_tube_Segment_program_456[Energy_TXD(Heat_B,10)];
                                                                P43=1;
                                                                                break;
                                        case 11 :                                        //DS6_1       
                                                                P43=0;
                                                                if(!key_service_Lock)
                                                                key_select();
                                                                P2=Digital_tube_Segment_program_456[Energy_TXD(Heat_A,1)];
                                                                P45=1;
                                                                                break;
                                        case 12:                                         //DS6_10       
                                                                P45=0;
                                                                if(!key_service_Lock)
                                                                key_select();
                                                                P2=Digital_tube_Segment_program_456[Energy_TXD(Heat_A,10)];
                                                                P44=1;
                                                                                break;
                                        case 13 :                                         //D1~D8
                                                                P44=0;       
                                                                if(!key_service_Lock)
                                                                key_select();
                                                                                if(Ion_mode==0)
                                                                                        P2=0xfb;
                                                                                        else if(Ion_mode==1)
                                                                                                P2=0xfd;
                                                                                                else
                                                                                                        P2=0xfe;
                                                                                                       P11=1;
                                                                                break;
                                        case 14 :                                        //D19~D16
                                                                P11=0;
                                                                if(!key_service_Lock)
                                                                key_select();
                                                                                if(start_Time)
                                                                                        P2=0xf7;
                                                                                else P2=0xff;
                                                                P42=1;
                                                                                break;
                                        case 15 :                                        //D17~D21
                                                                P42=0;
                                                                if(!key_service_Lock)
                                                                key_select();
                                                                P05=1;
                                                                                break;
                                                                        default:break;
                                }
                        if(Reuse_count>=15)
                                Reuse_count=0;
        }
}
}      //大循环到止
void key_select()             //按键扫描函数
{       
        uchar i;
        Bidirectional_IO();    //P46,P13,P15 设用准双口
        for(i=1;i<=8;i++)
        {
        switch(i)                                                                         //按键服务状态切换
                {
                        case 1:          P2=0x7f;                                //扫描按键  复用IO输出O
                                                _nop_();               //这里不加空操作,会读不到
                                                _nop_();
                                                if(P13==0)            //判断IO是否拉低
                                                {KeySec =7; key_service_Lock=~key_service_Lock;return;}            //缓存对应按键 ,循环标志位取反,放开TO内部函数
                                                else if(P46==0)      //判断IO是否拉低
                                                {KeySec =12; key_service_Lock=~key_service_Lock;return;}           //缓存对应按键 ,循环标志位取反,
                                                               
                                  break;
                        case 2:                P2=0xbf;
                                               
                                                if(P13==0)
                                                {KeySec =9; key_service_Lock=~key_service_Lock;return;}               
                                                else if(P46==0)
                                                {KeySec =1;key_service_Lock=~key_service_Lock;return;}       
                                                                       
                                  break;  
                        case 3:                P2=0xdf;
                                               
                                                if(P13==0)
                                                {KeySec =8;        key_service_Lock=~key_service_Lock;return;}               
                                                else if(P46==0)
                                                {KeySec =3; key_service_Lock=~key_service_Lock;return;}       
                                                                               
                                  break;           
                        case 4:                P2=0xef;
                                               
                                                if(P13==0)
                                                       
                                                {KeySec        =5;        key_service_Lock=~key_service_Lock;return;}               
                                                else if(P15==0)
                                                {KeySec =18; key_service_Lock=~key_service_Lock;return;}       
                                                else if(P46==0)
                                                {KeySec =14; key_service_Lock=~key_service_Lock;return;}       
                                                                                                                                       
                                  break;           
                        case 5:                P2=0xf7;       
                                               
                                                if(P13==0)
                                               
                                                {KeySec        =6; key_service_Lock=~key_service_Lock;return;}                       
                                                else if(P15==0)
                                                {KeySec =17; key_service_Lock=~key_service_Lock;return;}       
                                                else if(P46==0)
                                                {KeySec =4; key_service_Lock=~key_service_Lock;return;}       
                                                                               
                                  break;           
                        case 6:         P2=0xfb;
                                               
                                                if(P15==0)
                                                {KeySec =15; key_service_Lock=~key_service_Lock;return;}       
                                                else if(P46==0)
                                                {KeySec =2; key_service_Lock=~key_service_Lock;return;}       
                                                                                                                       
                                  break;
                        case 7:                P2=0xfd;
                                               
                                                if(P15==0)
                                                {KeySec =19; key_service_Lock=~key_service_Lock;return;}       
                                                else if(P46==0)
                                                {KeySec =13; key_service_Lock=~key_service_Lock;return;}       
                                                                               
                                  break;  
                        case 8:                P2=0xfe;
                                               
                                                if(P15==0)
                                                {KeySec =16; key_service_Lock=~key_service_Lock;return;}       
                                                else if(P46==0)
                                                {KeySec =11; key_service_Lock=~key_service_Lock;return;}       
                                                                                       
                                  break;           
        default: break;       

                }
        }
        High_IO();    //P46,P13,P15 设用高阻
}
void TM0_Isr() interrupt 1                                        //定时器0中断
{       
        if(!Reuse)
        Reuse=~Reuse;
       
        if(key_service_Lock)             //循环标志位取反,进入中断
        {
                        KeyTimeCnt++;
                if(KeyTimeCnt>=20)     //大于20Ms
                {        P0&=0xc0;         //拉低循环过程中位选
                        P11=0;             //拉低循环过程中位选
                        P3&=0x1f;        //拉低循环过程中位选
                        P4&=0x43;        //拉低循环过程中位选
                        KeyTimeCnt=0;   
                        key_service_Lock=~key_service_Lock;      ////循环标志位取反,防止进入中断,开放循环扫描
                        key_service_tmp=KeySec;                          //缓存上次扫描结果
                        key_select();                                           //再次扫描
                        if(key_service_tmp==KeySec)                 //对比扫描结果
                        {
                                key_service();                                      //调用按键服务程序
                        }
                        //else KeySec=0;
                       P0|=0xc0;        
                        P11=1;            
                        P3|=0x1f;        
                        P4|=0x43;        
                }
        }
       
        }
请问怎么优化,还有_nop_(); 那里原因,谢谢

回复

使用道具 举报

ID:1019604 发表于 2022-4-19 09:22 | 显示全部楼层
按键扫描时
所有位输出置0
P46/P13/P15设为双向弱上拉并置1
把段输出设为0xFE,并检测P46/P13有没有拉低,有就是key3/key8被按下
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表