请问这个电路怎么加一个显示闭合开关sql 数量加一的数码管?

关于数控电路中数码管怎么显示灯亮个数_百度知道怎么用数码管显示可连续加减乘除的计算器 - 单片机论坛 -
中国电子技术论坛 -
最好最受欢迎电子论坛!
后使用快捷导航没有帐号?
怎么用数码管显示可连续加减乘除的计算器
22:38:29  
这是我在一个只能加减、而且不能连续的计算器程序基础上改的,但是不知道怎么改能让它可以连续运算,求帮助。
就直接发运算部分了。
void KeyAction(unsigned char keycode)
& & static char oprt =0;
& & static unsigned long result = 0;&&//用于保存运算结果
& & static unsigned long addend = 0;&&//用于保存输入的加数
& & if ((keycode&=0x30) && (keycode&=0x39))&&//输入0-9的数字
& && &&&addend = (addend*10)+(keycode-0x30); //整体十进制左移,新数字进入个位
& && &&&ShowNumber(addend);& & //运算结果显示到数码管
& & & & else if (keycode == 0x26)&&//向上键用作加号
& && &&&oprt = 0;& && && && &&&//设置运算符变量
& && &&&result =& && & //运算数存到结果中,准备进行加减
& && &&&addend = 0;& && && && &//清零运算数,准备接收下一个运算数
& && &&&ShowNumber(addend);& & //刷新数码管显示
& & else if (keycode == 0x28)&&//向下键用作减号
& && &&&oprt = 1;& && && && &&&//设置运算符变量
& && &&&result =& && & //运算数存到结果中,准备进行加减
& && &&&addend = 0;& && && && &//清零运算数,准备接收下一个运算数
& && &&&ShowNumber(addend);& & //刷新数码管显示
& & & & else if (keycode ==0x25)
& & & && && &oprt=2;
& & & & & & & &&&result =& & & & & & & & & & & & & & & & //乘
& & & & & & & &&&addend=0;
& & & & & & & &&&ShowNumber(addend);
& & & & else if (keycode ==0x27)
& & & && && &oprt=3;
& & & & & & & &&&result =& & & & & & & & & & & & & & & &&&//除
& & & & & & & &&&addend=0;
& & & & & & & &&&ShowNumber(addend);
& & else if (keycode == 0x0D)&&//回车键,执行加减运算
& && &&&if (oprt == 0)
& && && && &result +=&&//进行加法运算
& && &&&else if(oprt==1)
& && && && &result -=&&//进行减法运算
& & & & & & & & else if(oprt==2)
& & & & & & & & {
& & & & & & & && &&&result *=& & & & //乘
& & & & & & & & }
& & & & & & & & else if(oprt==3)
& & & & & & & & {
& & & & & & & && &&&result /=& & & && &//除
& & & & & & & & }
& && &&&addend = 0;
& && &&&ShowNumber(result);& & //运算结果显示到数码管
& &else if (keycode == 0x1B)&&//Esc键,清零结果
& && &&&addend = 0;
& && &&&result = 0;
& && &&&ShowNumber(addend);& & //清零后的加数显示到数码管
08:48:04  
连续只要不断查询按键不就可以了,最简单的是加一个大循环。让你的KeyAction一直工作。不知道理解对没
高级工程师
09:24:17  
我有个这方面的代码,用iar编译的
12:41:02  
我有个这方面的代码,用iar编译的
我这是用的金沙滩工作室的那款单片机,能借鉴吗
12:41:29  
连续只要不断查询按键不就可以了,最简单的是加一个大循环。让你的KeyAction一直工作。不知道理解对没
怎么写啊,我都晕了
13:56:00  
怎么写啊,我都晕了
你的KeyAction在主程序里怎么摆的?
助理工程师
17:48:54  
就是一个按键扫描&&然后返回按键值& &
08:12:42  
你的KeyAction在主程序里怎么摆的?
这是全部了
#include &reg52.h&
sbit ADDR0 = P1^0;
sbit ADDR1 = P1^1;
sbit ADDR2 = P1^2;
sbit ADDR3 = P1^3;
sbit ENLED = P1^4;
sbit KEY_IN_1&&= P2^4;
sbit KEY_IN_2&&= P2^5;
sbit KEY_IN_3&&= P2^6;
sbit KEY_IN_4&&= P2^7;
sbit KEY_OUT_1 = P2^3;
sbit KEY_OUT_2 = P2^2;
sbit KEY_OUT_3 = P2^1;
sbit KEY_OUT_4 = P2^0;
unsigned char code LedChar[] = {&&//数码管显示字符转换表
& & 0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,
& & 0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E
unsigned char LedBuff[6] = {&&//数码管显示缓冲区
& & 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
unsigned char code KeyCodeMap[4][4] = { //矩阵按键编号到标准键盘键码的映射表
& & { 0x31, 0x32, 0x33, 0x26 }, //数字键1、数字键2、数字键3、向上键
& & { 0x34, 0x35, 0x36, 0x25 }, //数字键4、数字键5、数字键6、向左键
& & { 0x37, 0x38, 0x39, 0x28 }, //数字键7、数字键8、数字键9、向下键
& & { 0x30, 0x1B, 0x0D, 0x27 }&&//数字键0、ESC键、&&回车键、 向右键
unsigned char KeySta[4][4] = {&&//全部矩阵按键的当前状态
& & {1, 1, 1, 1},&&{1, 1, 1, 1},&&{1, 1, 1, 1},&&{1, 1, 1, 1}
void KeyDriver();
void main()
& & EA = 1;& && & //使能总中断
& & ENLED = 0;& & //选择数码管进行显示
& & ADDR3 = 1;
& & TMOD = 0x01;&&//设置T0为模式1
& & TH0&&= 0xFC;&&//为T0赋初值0xFC67,定时1ms
& & TL0&&= 0x67;
& & ET0&&= 1;& &&&//使能T0中断
& & TR0&&= 1;& &&&//启动T0
& & LedBuff[0] = LedChar[0];&&//上电显示0
& & while (1)
& && &&&KeyDriver();& &//调用按键驱动函数
/* 将一个有符号长整型的数字显示到数码管上,num-待显示数字 */
void ShowNumber(long num)
& & unsigned char buf[6];
& & if (num & 0)&&//首先提取并暂存符号位
& && &&&sign = 1;
& && &&&num = -
& && &&&sign = 0;
& & for (i=0; i&6; i++)& &//把长整型数转换为6位十进制的数组
& && &&&buf = num % 10;
& && &&&num = num / 10;
& & for (i=5; i&=1; i--)&&//从最高位起,遇到0转换为空格,遇到非0则退出循环
& && &&&if (buf == 0)
& && && && &LedBuff = 0xFF;
& && &&&else
& && && && &
& & if (sign != 0)& && &&&//负数时,需在最前面添加负号
& && &&&if (i & 5)& && &&&//当有效位数小于6位时添加负号,否则显示结果将是错的
& && && && &LedBuff[i+1] = 0xBF;
& & for ( ; i&=0; i--)& & //剩余低位都如实转换为数码管显示字符
& && &&&LedBuff = LedChar[buf];
/* 按键动作函数,根据键码执行相应的操作,keycode-按键键码 */
void KeyAction(unsigned char keycode)
& & static char oprt = 0;& & //用于保存加减运算符
& & static long result = 0;&&//用于保存运算结果
& & static long addend = 0;&&//用于保存输入的加数
& & if ((keycode&=0x30) && (keycode&=0x39))&&//输入0-9的数字
& && &&&addend = (addend*10)+(keycode-0x30); //整体十进制左移,新数字进入个位
& && &&&ShowNumber(addend);& & //运算结果显示到数码管
& & else if (keycode == 0x26)&&//向上键用作加号
& && &&&oprt = 0;& && && && &&&//设置运算符变量
& && &&&result =& && & //运算数存到结果中,准备进行加减
& && &&&addend = 0;& && && && &//清零运算数,准备接收下一个运算数
& && &&&ShowNumber(addend);& & //刷新数码管显示
& & else if (keycode == 0x28)&&//向下键用作减号
& && &&&oprt = 1;& && && && &&&//设置运算符变量
& && &&&result =& && & //运算数存到结果中,准备进行加减
& && &&&addend = 0;& && && && &//清零运算数,准备接收下一个运算数
& && &&&ShowNumber(addend);& & //刷新数码管显示
& & & & else if (keycode ==0x25)
& & & && && &oprt=2;
& & & & & & & &&&result=& & & & & & & & & & & & & & & & //乘
& & & & & & & &&&addend=0;
& & & & & & & &&&ShowNumber(addend);
& & & & else if (keycode ==0x27)
& & & && && &oprt=3;
& & & & & & & &&&result=& & & & & & & & & & & & & & & &&&//除
& & & & & & & &&&addend=0;
& & & & & & & &&&ShowNumber(addend);
& & else if (keycode == 0x0D)&&//回车键,执行加减运算
& && &&&if (oprt == 0)
& && && && &result +=&&//进行加法运算
& && &&&else if(oprt==1)
& && && && &result -=&&//进行减法运算
& & & & & & & & else if(oprt==2)
& & & & & & & & {
& & & & & & & && &&&result *=& & & & //乘
& & & & & & & & }
& & & & & & & & else if(oprt==3)
& & & & & & & & {
& & & & & & & && &&&result /=& & & && &//除
& & & & & & & & }
& && &&&addend = 0;
& && &&&ShowNumber(result);& & //运算结果显示到数码管
& & else if (keycode == 0x1B)&&//Esc键,清零结果
& && &&&addend = 0;
& && &&&result = 0;
& && &&&ShowNumber(addend);& & //清零后的加数显示到数码管
/* 按键驱动函数,检测按键动作,调度相应动作函数,需在主循环中调用 */
void KeyDriver()
& & unsigned char i,
& & static unsigned char backup[4][4] = {&&//按键值备份,保存前一次的值
& && &&&{1, 1, 1, 1},&&{1, 1, 1, 1},&&{1, 1, 1, 1},&&{1, 1, 1, 1}
& & for (i=0; i&4; i++)&&//循环检测4*4的矩阵按键
& && &&&for (j=0; j&4; j++)
& && && && &if (backup[j] != KeySta[j])& & //检测按键动作
& && && && &{
& && && && && & if (backup[j] != 0)& && && &&&//按键按下时执行动作
& && && && && & {
& && && && && && &&&KeyAction(KeyCodeMap[j]); //调用按键动作函数
& && && && && & }
& && && && && & backup[j] = KeySta[j];& &&&//刷新前一次的备份值
& && && && &}
/* 按键扫描函数,需在定时中断中调用,推荐调用间隔1ms */
void KeyScan()
& & static unsigned char keyout = 0;& &//矩阵按键扫描输出索引
& & static unsigned char keybuf[4][4] = {&&//矩阵按键扫描缓冲区
& && &&&{0xFF, 0xFF, 0xFF, 0xFF},&&{0xFF, 0xFF, 0xFF, 0xFF},
& && &&&{0xFF, 0xFF, 0xFF, 0xFF},&&{0xFF, 0xFF, 0xFF, 0xFF}
& & //将一行的4个按键值移入缓冲区
& & keybuf[keyout][0] = (keybuf[keyout][0] && 1) | KEY_IN_1;
& & keybuf[keyout][1] = (keybuf[keyout][1] && 1) | KEY_IN_2;
& & keybuf[keyout][2] = (keybuf[keyout][2] && 1) | KEY_IN_3;
& & keybuf[keyout][3] = (keybuf[keyout][3] && 1) | KEY_IN_4;
& & //消抖后更新按键状态
& & for (i=0; i&4; i++)&&//每行4个按键,所以循环4次
& && &&&if ((keybuf[keyout] & 0x0F) == 0x00)
& && &&&{& &//连续4次扫描值为0,即4*4ms内都是按下状态时,可认为按键已稳定的按下
& && && && &KeySta[keyout] = 0;
& && &&&else if ((keybuf[keyout] & 0x0F) == 0x0F)
& && &&&{& &//连续4次扫描值为1,即4*4ms内都是弹起状态时,可认为按键已稳定的弹起
& && && && &KeySta[keyout] = 1;
& & //执行下一次的扫描输出
& & keyout++;& && && && && & //输出索引递增
& & keyout = keyout & 0x03;&&//索引值加到4即归零
& & switch (keyout)& && && & //根据索引,释放当前输出引脚,拉低下次的输出引脚
& && &&&case 0: KEY_OUT_4 = 1; KEY_OUT_1 = 0;
& && &&&case 1: KEY_OUT_1 = 1; KEY_OUT_2 = 0;
& && &&&case 2: KEY_OUT_2 = 1; KEY_OUT_3 = 0;
& && &&&case 3: KEY_OUT_3 = 1; KEY_OUT_4 = 0;
& && &&&default:
/* 数码管动态扫描刷新函数,需在定时中断中调用 */
void LedScan()
& & static unsigned char i = 0;&&//动态扫描的索引
& & P0 = 0xFF;& &//显示消隐
& & switch (i)
& && &&&case 0: ADDR2=0; ADDR1=0; ADDR0=0; i++; P0=LedBuff[0];
& && &&&case 1: ADDR2=0; ADDR1=0; ADDR0=1; i++; P0=LedBuff[1];
& && &&&case 2: ADDR2=0; ADDR1=1; ADDR0=0; i++; P0=LedBuff[2];
& && &&&case 3: ADDR2=0; ADDR1=1; ADDR0=1; i++; P0=LedBuff[3];
& && &&&case 4: ADDR2=1; ADDR1=0; ADDR0=0; i++; P0=LedBuff[4];
& && &&&case 5: ADDR2=1; ADDR1=0; ADDR0=1; i=0; P0=LedBuff[5];
& && &&&default:
/* T0中断服务函数,用于数码管显示扫描与按键扫描 */
void InterruptTimer0() interrupt 1
& & TH0 = 0xFC;&&//重新加载初值
& & TL0 = 0x67;
& & LedScan();& &//调用数码管显示扫描函数
& & KeyScan();& &//调用按键扫描函数
Powered by按键数码管显示复用后冲突问题
用的51单片机,附电路图。
按键KEY与数码管COM端是复用的。
现在可以知道,把数码管的数据输出端设置为高阻输入。
按键即(COM)端,设置为标准IO口,可以检测到按键输入。
数码管显示时,
数码管的数据输出端设置为推挽输出。
按键即(COM)端,同时要设置为推挽才可以显示正常,
数码管显示用的是定时器中断显示。(6ms)。
按键在主循环,扫描输入(100ms)扫描1次。
用了按键程序,LED显示不正常。
用了LED显示程序,按键程序不正常。
不知道为什么?有没有人指一下点?
本帖子中包含更多资源
才可以下载或查看,没有帐号?
没有人看,自己顶一下
显示的时候不要扫描键盘
共阴数码管,则com1~com4会循环输出低电平.R1接地端改为接VCC,R1的另一端接单片机IO,当comX输出低电平后,读取R1连接的IO状态,如果为低电平,则有按键按下,并且这个按键就是连接comX的那个按键.此电路的缺点是不能同时按下两个按键,如果要支持同时按下两个按键,则每个按键与R1连接间加入一个二极管进行隔离,二极管方向是从R1流向按键.
这个电路不需要同时按下两个按键的。
按键的时候,我已经把定时器关闭了的。
void Display_Led ( void )
& & & & g_byLedCount++;
& & & & if(g_byLedCount &= 4)& & & & & & & & & & & & & & & & & & & & & & & & //重新开始
& & & & & & & & g_byLedCount = 0;
& & & & }& & & &
& & & & value = Display_Tab[g_DisplayBuff[g_byLedCount]];& & & &
& & & & P1M0 &= ~0& & & & //数据端设置推挽输出
& & & & P1M1 |= 0& && & & &
& & & & P2M0 &= ~0x06;&&& & & & //数据端设置推挽输出
& & & & P2M1 |= 0x06;& &
& & & & P2M1 |= 0x20;& && && &//公共端设置推挽输出
& & & & P3M1 |= 0x1c;
& & & & P16 = (bit) (value & 0x80);
& & & & P21 = (bit) (value & 0x40);
& & & & P13 = (bit) (value & 0x20);
& & & & P14 = (bit) (value & 0x10);
& & & & P15 = (bit) (value & 0x08);
& & & & P17 = (bit) (value & 0x04);
& & & & P12 = (bit) (value & 0x02);
& & & & P22 = (bit) (value & 0x01);
& & & & switch(g_byLedCount)//循环扫描
& & & & {& & & &
& & & & & & & & case 0:
& & & & & & & & {& & & & & & & &
& & & & & & & & & & & & COM1 = 0;
& & & & & & & & & & & & COM2 = 1;
& & & & & & & & & & & & COM3 = 1;
& & & & & & & & & & & & COM4 = 1;
& & & & & & & & }
& & & & & & & &
& & & & & & & & case 1:
& & & & & & & & {
& & & & & & & & & & & & COM1 = 1;
& & & & & & & & & & & & COM2 = 0;
& & & & & & & & & & & & COM3 = 1;
& & & & & & & & & & & & COM4 = 1;
& & & & & & & & }& & & & & & & & & & & &
& & & & & & & & case 2:
& & & & & & & & {
& & & & & & & & & & & & COM1 = 1;
& & & & & & & & & & & & COM2 = 1;
& & & & & & & & & & & & COM3 = 0;
& & & & & & & & & & & & COM4 = 1;
& & & & & & & & }& & & & & & & &
& & & & & & & & case 3:
& & & & & & & & {
& & & & & & & & & & & & COM1 = 1;
& & & & & & & & & & & & COM2 = 1;
& & & & & & & & & & & & COM3 = 1;
& & & & & & & & & & & & COM4 = 0;
& & & & & & & & }
& & & & & & & &
& & & & & & & & default :
Byte Get_Key ( void )
& & & & BYTE byKey = 0;
& && & ET0 = 0;& & & & & & & & //关闭中断(即关闭led扫描)
& & & & P1M0 |= 0& &//按键时,数据端高阻输入
& & & & P1M1 &= ~0& & & &
& & & & P2M0 |= 0x06;& &//按键时,数据端高阻输入
& & & & P2M1 &= ~0x06;
& & & & P2M1 &= ~0x20;& & & & //按键时,公共端标准IO口
& & & & P3M1 &= ~0x1c;
& & & & if ( KEY_MENU == 0 )//是否按键了。
& & & & & & & &&&byKey = 1;
& & & & & & & &&&goto&&KEY_EXIT;
& & & & if ( KEY_UP == 0 ) //是否按键了。
& & & & & & & &&&byKey = 2;
& & & & & & & &&&goto&&KEY_EXIT;
& & & & if ( KEY_DOWN == 0 )//是否按键了。
& & & & & & & &&&byKey = 3;
& & & & & & & &&&goto&&KEY_EXIT;
& & & & if ( KEY_ENTER == 0 )//是否按键了。
& & & & & & & &&&byKey = 4;
KEY_EXIT:& & & & & & & &
& & & & ET0 = 1;& &&&& & & & & & & & & & & & & & & & & & & & //打开扫描显示
& & & & return byK
按理说,扫描和按键,我都是重新设定端口方向的。为什么还是会相互有影响?
貌似这样不行吧,用个74hc595试试啊
硬件是这样做的,别人这样用可以。
扫描时间太长了吧,显示的时间也长,按键的时间也长
6MS*4=24MS了,也算可以吧
按键100MS就太长了,要是10次消抖动的话,岂不是1秒钟才能反应过来?
说一下我的设计习惯,把按键的COM接到一个IO上,每个按键串联二极管(防止两个同时按下时影响显示),在扫描显示输出的时候,读一下这个IO就行了,这样不用来回倒腾什么推挽啥的了,简单方便。我用的定时中断是2MS的,消抖动是计数10次有效,否则视为无效。
本帖最后由 xiaobendan001 于
09:57 编辑
wenking99 发表于
硬件是这样做的,别人这样用可以。
你要这样用也可以,显示用共阴的,然后不要分开操作,也不要去搞什么推挽了,就标准IO,就是定时器中断里面扫描输出后其他三个点是高电平的,此时检测这三个按键即可,这个开关下面的电阻有可能是高亮的数码管产生一点亮度,估计不会很明显。
看你的程序应该就是共阴的吧。
void key_scan(void)
& & P2IO &=0xe1;& && && && && && && && &&&//**//
& & delay(100);
& & key_buf=0;& && && && && && && && && & //清按键值
& & P1&=0x02;& && && && && && && && && &&&//关显示
& & key_com=0;& && && && && && && && && & //开启按键公共端
& & delay(100);
& & if(key_2==0){key_buf|=0x01;}& && && & //读按键1
& & if(key_3==0){key_buf|=0x02;}& && && & //读按键2
& & if(key_4==0){key_buf|=0x04;}& && && & //读按键3
& & if(key_5==0){key_buf|=0x08;}& && && & //读按键4
& & P2IO |=0x1e;& && && && && && && && &&&//**//
& & key_com=1;& && && && && && && && && & //释放按键公共端
& & if(key_buf==0)& && && && && && && && &//无键
& && &&&keyup_bit=0;& && && && && && && & //按键释放标志
& && &&&flash_not_bit=0;
& && &&&key_cnt_short=0;& && && && && && &//清去抖计数
& && &&&key_cnt_long=0;& && && && && && & //清长按计数
& & else& && && && && && && && && && && & //有键处理
& && &&&if(keyup_bit)& && && && && && && &//按键按下标志
& && && && &if(++key_cnt_long&=200)& && &&&//长按 40-&200
& && && && &{
& && && && && & key_cnt_long-=50;& && && &//4Hz& &15-&50
& && && && && & flash_not_bit=1;& && && & //快速调节不闪烁
& && && && && & key_pro();& && && && && & //按键处理
& && && && &}
& && && && &else
& && && && &{
& && && && && &
& && && && &}
& && &&&else& && && && && && && && && && &//
& && && && &if(++key_cnt_short&=20)& && & //去抖&&5-&20
& && && && &{
& && && && && & key_cnt_short=0;
& && && && && & keyup_bit=1;& && && && &&&//短按
& && && && && & short_buz(1,short_buz_time);
& && && && && & key_pro();
& && && && &}
这个是长短按键处理吧。
因为共阴极没有用三极管驱动,要点亮数码管,必须要设定公共端为推挽输出,数码管数据端也必须设定为推挽输出才能点亮。
其它方式都不行。
要按键检测也必须设定数码管数据端为高阻输入,数码管公共端,即按键检测端为标准IO,才可以检测到按键。
其它方式都不行。
所以上述程序为什么要先设定端口模式的原因。
& & & & while ( 1 )
& & & & & & & & WDT_action();//喂狗
& & & & & & & & if ( g_time_5MS_Fg )//5ms数码管显示
& & & & & & & & {
& & & & & & & & & & & & g_time_5MS_Fg = 0;
& & & & & & & & & & & & Display_Led();//LED显示程序不能跟下面Get_Key按键检测同时,用了数码管会闪,没有按键也会按下输出。
& & & & & & & & & & & & g_key_scan_count++;
& & & & & & & & & & & &
& & & & & & & & & & & & if ( g_key_scan_count &= 20 )//100ms
& & & & & & & & & & & & {
& & & & & & & & & & & & & & & & g_key_scan_count = 0;
& & & & & & & & & & & & & & & & //key = Get_Key ( );
& & & & & & & & & & & & }
& & & & & & & & }
怎么不正常法?说来看看
我刚刚整了个140多个数码管,30多个按键,数据IO口复用的,显示跟按键扫描都很正常。
LED显示程序不能跟下面Get_Key按键检测同时,用了数码管会闪,没有按键也会按下输出数据。
我现在单独用按键测试
Byte Get_Key ( void )
& & & & BYTE byKey = 0;
& & & & P1M0 |= 0& & //数码管数据端高阻输入
& & & & P1M1 &= ~0& & & &
& & & & P2M0 |= 0x06;& &///数码管数据端高阻输入
& & & & P2M1 &= ~0x06;& & & & & & & &
& & & & P2M0 &= ~0x20;;& & & & //数码管公共端设置为标准IO口,即按键输入端
& & & & P2M1 &= ~0x20
& && &&&P3M0 &= ~0x1c;& && &&&& & & & //数码管公共端设置为标准IO口,即按键输入端
& & & & P3M1 &= ~0x1c;
& & & & P2 |= 0X20;& && && && &&&//设置按键输入引脚为高电平
& & & & P3 |= 0X1C;& && && && & //设置按键输入引脚为高电平
& & & & if ( P25 == 0 )//KEY_MENU按键按下
& & & && && & UartSendByte(1);& & & & //测试
& & & && && & byKey = 1;
& & & & //恢复推挽输出
& & & & //P1M0 &= ~0& & & & //数码管数据端设置为推挽输出
& & & & //P1M1 |= 0& && & & &
& & & & //P2M0 &= ~0x06; //数码管数据端设置为推挽输出
& & & & //P2M1 |= 0x06;& && & & &
& && &&&//P2M0 &= ~0x20;
& & & & //P2M1 |= 0x20;& &//数码管公共端设置为推挽输出
& && &&&//P3M0 &= ~0x1c;
& & & & //P3M1 |= 0x1c;& & //数码管公共端设置为推挽输出
& & & & return byK
如果只调试按键部分,很奇怪,为什么把后面注释部分加上去,按键都检测不到了。
扫描的时候,开始时不是都已经重新赋值了吗?
不明白怎么回事,高手指点。
/forum.php?mod=attachment&aid=MTEyNzkzfDU1YTUwZTJiYjBiZTYwZTRiOTE3OWM1MWNkMWJlMmFlfDE0NzczNzA3MjM%3D&request=yes&_f=.png
哎呀呀,把电路改成这样吧
本帖子中包含更多资源
才可以下载或查看,没有帐号?
key_int任意姐一个IO口吧
定时器一直开着;
while ( 1 )
& && && && && & WDT_action();//喂狗
& && && && && & if ( g_time_5MS_Fg )//5ms数码管显示
& && && && && & {
& && && && && && && && &g_time_5MS_Fg = 0;
& & & & & & & & & & & & & & & & & & & & & & & &
& & & & & & & & & & & & & & & & & & & & & & & & ////读按键
& & & & & & & & & & & & & & & & & & & & & & & & if(!key_io)
& & & & & & & & & & & & & & & & & & & & & & & & {
& & & & & & & & & & & & & & & & & & & & & & & & & & & & key_value |= (0x01 && g_byLedCount);
& & & & & & & & & & & & & & & & & & & & & & & & }
& & & & & & & & & & & & & & & & & & & & & & & & else
& & & & & & & & & & & & & & & & & & & & & & & & {
& & & & & & & & & & & & & & & & & & & & & & & & & & & & key_value &= ~(0x01 && g_byLedCount);
& & & & & & & & & & & & & & & & & & & & & & & & }
& & & & & & & & & & & & & & & & & & & & & & & &
& && && && && && && && &Display_Led();//LED显示程序不能跟下面Get_Key按键检测同时,用了数码管会闪,没有按键也会按下输出。
& && && && && && && && &g_key_scan_count++;
& && && && && && && &&&
& && && && && && && && &if ( g_key_scan_count &= 20 )//100ms
& && && && && && && && &{
& && && && && && && && && && &&&g_key_scan_count = 0;
& && && && && && && && && && &&&//key = Get_Key ( );
& && && && && && && && &}
& && && && && & }
接下来,消抖,按下,弹开,长按,多按键,都是原来的思路
ADC采集按键,轻松又愉快,想多少就搞多少
这样设计就是为了节省成本,所以用到这样方式。
我现在在扫描按键的时候,先把LED数码管公共端状态,还有数据端状态数据都保存,按键完成后,再恢复原来的状态。
又出现一个问题,按键检测不了。显示可以了。
上述电路如果改成那种方式,还需要多一个IO口来检测按键输入吧。
wenking99 发表于
上述电路如果改成那种方式,还需要多一个IO口来检测按键输入吧。
我说的没看懂啊
都说了不要把COM设置成推挽,你用共阴的数码管,接COM的脚只是灌电流,干嘛非得推挽?是否推挽的灌电流都一样的
如果COM端不设置为推挽数码管根本点不亮。因为IO口没有驱动电路。
进入Display_Led()函数时,首先调用Get_Key()函数,然后执行Display_Led()函数其它内容.
本帖最后由 xiaobendan001 于
13:50 编辑
wenking99 发表于
如果COM端不设置为推挽数码管根本点不亮。因为IO口没有驱动电路。
又有新发现,IO没有驱动?你用的神马单片机?
如此给你古老的89C51就更加不能使用了?
看脚的功能,似乎和我正在使用的STC12C5204AD是一样的,不知道对不对。
让我感到奇怪的是,你为什么不使用一整组IO驱动LED的8段,而是分到两组IO中了,这样程序不是很麻烦?效率很低?
我知道了,你说的没有驱动是把IO设置为输入了,高阻的那种了吧
还有一种方法你可以试试,你是4个数码管的,把你的扫描次数设定为5个,在第五次的时候关闭所有的数码管,令4个COM都处于输入状态,然后去读取你的按键吧。
我不是说没有驱动。一般情况下,要点亮数码管,公共端要加三极管等驱动电路。
这个电路没有什么三极管放大,只有把端口设置为推挽方式。因为推挽方式驱动电流有15-20MA.
是的,跟你那个STC一样的芯片
我打算改一下电路,把按键输入接到数码管的数据端。
我觉得不管用哪种方式,还是分时复用的问题。按键跟LED扫描冲突了。
推挽只是说其拉电流也可以达到这个值的,灌电流是一样的,仔细看看那个所谓的手册吧。
wenking99 发表于
我觉得不管用哪种方式,还是分时复用的问题。按键跟LED扫描冲突了。
本帖子中包含更多资源
才可以下载或查看,没有帐号?
进入Display_Led()函数时,首先调用Get_Key()函数,然后执行Display_Led()函数其它内容.
while ( 1 )
& && && && && & WDT_action();//喂狗
& && && && && & if ( g_time_5MS_Fg )//5ms数码管显示
& && && && && & {
& && && && && && && && &g_time_5MS_Fg = 0;
& && && && && && && && &
& && && && && && && && &g_key_scan_count++;
& && && && && && && && &
& && && && && && && && &if ( g_key_scan_count &= 20 )//100ms
& && && && && && && && &{
& && && && && && && && && && &&&g_key_scan_count = 0;
& && && && && && && && && && &&&key = Get_Key ( );& && && && && && && &&&
& && && && && && && && &}
& && && && && && && && & Display_Led();/
& && && && && & }
我觉得这样子做,显示和按键都是分开的。为什么还按键还是没有检测到?
while ( 1 )
& && && && && & WDT_action();//喂狗
& && && && && & if ( g_time_5MS_Fg )//5ms数码管显示
& && && && && & {
& && && && && && && && &g_time_5MS_Fg = 0;
& && && && && && && && &
& && && && && && && && &g_key_scan_count++;& && && && && && && && &
& && && && && && && &
& && && && && && && && & Display_Led();//
& && && && && && && && &&&if ( g_key_scan_count &= 20 )//100ms扫描一次按键
& && && && && && && && & {
& && && && && && && && && && &&&g_key_scan_count = 0;
& && && && && && && && && && &&&key = Get_Key ( );& && &&&//这里要连续扫描两次才能输出键值& && && && && && &
& && && && && && && && && && &&&key = Get_Key ( );& && &&&//这里要连续扫描两次才能输出键值& &
& && && && && && && && & }
& && && && && & }
但是上面会出现一个问题。按下时4个数码管会闪,长按会不停闪,频率大概是1秒闪一次。
不知道为什么要连续扫描两次按键才有数据输出,
而且数码管会闪烁。
P2M0 &= ~0x20;;& && &&&//数码管公共端设置为标准IO口,即按键输入端
P2M1 &= ~0x20
P3M0 &= ~0x1c;& && && && && & //数码管公共端设置为标准IO口,即按键输入端
P3M1 &= ~0x1c;
P2 |= 0X20;& && && && &&&//设置按键输入引脚为高电平
P3 |= 0X1C;& && && && & //设置按键输入引脚为高电平
P2M0 &= ~0x20;;& && &&&//数码管公共端设置为标准IO口,即按键输入端
P2M1 &= ~0x20
P3M0 &= ~0x1c;& && && && && & //数码管公共端设置为标准IO口,即按键输入端
P3M1 &= ~0x1c;
P2 |= 0X20;& && && && &&&//设置按键输入引脚为高电平
P3 |= 0X1C;& && && && & //设置按键输入引脚为高电平
进一步发现这个按键模式,及电平要设置两次,才行。
难道是延时不够?
进一步发现,只要在按键检测前加一个延时1us就可以正常按键,LED显示也正常了。
void delay_us ( BYTE time )
& & & & BYTE
& & & & for (i=0; i& i++)
& & & & & & & & ;
Byte Get_Key ( void )
& && &&&BYTE byKey = 0;
& && &&&P1M0 |= 0& & //数码管数据端高阻输入
& && &&&P1M1 &= ~0& && &&&
& && &&&P2M0 |= 0x06;& &///数码管数据端高阻输入
& && &&&P2M1 &= ~0x06;& && && && && &
& && &&&P2M0 &= ~0x20;;& && &&&//数码管公共端设置为标准IO口,即按键输入端
& && &&&P2M1 &= ~0x20
& && &&&P3M0 &= ~0x1c;& && && && && & //数码管公共端设置为标准IO口,即按键输入端
& && &&&P3M1 &= ~0x1c;
& && &&&P2 |= 0X20;& && && && &&&//设置按键输入引脚为高电平
& && &&&P3 |= 0X1C;& && && && & //设置按键输入引脚为高电平
& && & delay_us(1);& && && && & //延时1uS再读引脚电平。
& && &&&if ( P25 == 0 )//KEY_MENU按键按下
& && && && &&&UartSendByte(1);& && &&&//测试
& && && && &&&byKey = 1;
& && &&&return byK
wenking99 发表于
我不是说没有驱动。一般情况下,要点亮数码管,公共端要加三极管等驱动电路。
这个电路没有什么三极管放大 ...
接数码管阳极的管脚才需要设置成推挽输出,数码管阴极的,默认的输出就可以了。
你的是共阴数码管,不需要设置成推挽输出,程序里也就没这么多PxM0,PxM1的操作了。
wenking99 发表于
进一步发现,只要在按键检测前加一个延时1us就可以正常按键,LED显示也正常了。
void delay_us ( BYTE tim ...
你用多少频率的晶振?
还是那个问题,没仔细看PDF文件,加延时的问题,在PDF文件里面有提及。
要踏实,不要浮躁!
接数码管阳极的管脚才需要设置成推挽输出,数码管阴极的,默认的输出就可以了。
你的是共阴数码管,不需要设置成推挽输出,程序里也就没这么多PxM0,PxM1的操作了。
我试过,数码管驱动和数据端必须设置为推挽输出,才可以点亮。
我晶振是24MHZ的
我也经常是这样子用,主程序2ms刷新一次,每次刷新一位数码管,或者说显示COM,数码管刷完了,再一个周期去做按键检测就可以了
static uint8_t mDisplayI
switch ( mDisplayIndex )
case 0:...;mDisplayIndex = 1;
case 1:...;mDisplayIndex = 2;
case 2:...;mDisplayIndex = 3;
case 3:...;mDisplayIndex = 4;
case 4: Key_Read();&&;mDisplayIndex = 0;
显示的时候要设置成推挽输出,做按键检测的时候,要先关闭显示,把复用做按键检测的设置为输入带上拉
wenking99 发表于
接数码管阳极的管脚才需要设置成推挽输出,数码管阴极的,默认的输出就可以了。
你的是共阴数码管,不需要 ...
数据端是要推挽的,因为你要用他的拉电流,COM就不用了吧,因为你只用他的灌电流。
24M是要加延时读取IO的,在PDF里面有,我用的6M的,似乎没有用过延时读取,不过我不是一次读取的,而是分几次的,而且我读取时往往在之前先做点别的什么,这样就不要专门的去延时了。
硬件不用改,软件很多办法可以用的,仔细琢磨一下吧。
还有,再重复一下,要仔细看PDF文件,尽管那个是有点乱。
刚才再试了一下,数码管数据端IO口设置为推挽输出,公共端设置为标准IO口,
这样是可以点亮数码管,也可以不加延时就可以检测到按键输入。
但电路中按键加了一个5.1K的下拉电阻,按键的时候,对应的数码管显示会闪烁。
或者说按键的时候,出现低亮度现象。
已经OK了。
数码显示正常,按键按下,数码管无任何闪烁,鬼影。
如果采用其他方式,比如数码管数据输出端采用推挽,数码管公共端采用标准I0模式,数码管可以正常显示,但是长按键时,有鬼影(即可以看到对应按键按下的数码管有低亮现象)。
程序流程如下:
按键扫描的时候数码管数据端采用高阻方式。
数码管公共端,即按键输入端采用标准IO方式。置按键电平为高。
然后延时1us.
再读取低电平,判断是否有键按下。
LED扫描的时候,数码管数据端与公共端都设置为推挽输出。
数码管扫描5MS扫描一次,
扫描扫描40MS扫描一次。
while ( 1 )
& && && && && & WDT_action();//喂狗
& && && && && & if ( g_time_5MS_Fg )//5ms数码管显示
& && && && && & {
& && && && && && && && &g_time_5MS_Fg = 0;
& && && && && && && && &
& && && && && && && && &g_key_scan_count++;& && && && && && && && &
& && && && && && && &
& && && && && && && && & Display_Led();//
& && && && && && && && &&&if ( g_key_scan_count &=8 )//40Ms扫描一次按键(小于40MS,LED显示会出现闪烁,估计是是高阻到推挽输出有延迟,或者从标准IO到推挽有延迟。)
& && && && && && && && & {
& && && && && && && && && && &&&g_key_scan_count = 0;
& && && && && && && && && && &&&key = Get_Key ( );& && &&&//这里要连续扫描两次才能输出键值& && && && && && &
& && && && && && && && & }
& && && && && & }
谢谢大家。
今天又优化了一下,效果很好,真正实现了分时复用。
按上面那位楼主xiaobendan001说的,
还有一种方法你可以试试,你是4个数码管的,把你的扫描次数设定为5个,在第五次的时候关闭所有的数码管,令4个COM都处于输入状态,然后去读取你的按键吧。
路过.学习一下....
ADC采集按键,轻松又愉快,想多少就搞多少
ADC能不能实现多个按键一起按?
阿莫电子论坛, 原"中国电子开发网"

我要回帖

更多关于 共阴极数码管 的文章

 

随机推荐