网站首页 > 技术文章 正文
8421编码开关种类繁多,按操作方式分有指拔式、旋转式;按制式分有二进制、十进制、十六进制等。每一位都有一个独立的BCD编码拨动盘,我们每选择的一个数字都由里面的印刷电路产生BCD编码,分别由下面的4个管脚输出。组合非常灵活,我们可以根据设计的需要,任意组合多个BCD编码拨动盘来组成多位的应用。
在单片机设计中,特别是工业应用的设计中,一些外部的数值设置我们经常会选择用到它。使用起来也比较方便。
一个8421编码拔动盘,如果是十进制的是数字0-9,如果是十六进制的数字是0-F。也就是说十进制有10个数字,十六进制有十六个数字。而8421编码正好可以编码16个数字,它的编码方式参考图1。
8421编码开关与单片机的硬件连接参考图2,这里以4位拔码盘为例。
图2中的电阻为限流电阻,阻值选择300R。二极管,是为了防止各位编码盘数据位的相互窜扰,可以选择1N4001。
读取编码盘的工作原理
单片机上电复位时,W1-W4保持高电平。我们用它们来读取各数据位的状态,在工作期间不去变更它们的电平状态,它们的电平状态将由D0-D3来决定。
在读取数据时,首先把D0-D4全部拉到高电平。D0拉为低电平,延时一段时间再分别去读取W1-W4的状态就可以知道4位编码盘的D0是什么状态。W1-W4读到的是低电平,那么说明相应4位编码盘的D0被编码了。用相同的方式去操作D1-D3就可以把完整的数值读取出来。
下面用程序来说明这一操作过程
/***********************拔码开关应用程序*************************/
#include <STC15F2K60S2.H>
int t_1ms, t_50ms; //这里定义的是1ms和50ms定时器,详细说明在上一课中有详细介绍
unsigned int Read_Switch[2], Read_Switch_Dec[2]; //定义读取到编码开关的16进制和10进制值的存储数组
void Read_8421_Switch();
void main()
{
Read_8421_Switch();
}
void Read_8421_Switch() //指拔开关设置值读取
{
static float scantime = 0;
static bit reachtime = 0, savetime = 0, R_W = 0;
static char switch_bite = 1;
char turnchar = 0, turncnt = 1, i;
static int turnchartmp[1], Read_Switch[1];
int turnmul = 0;
if(!savetime)
{
scantime = t_1ms;
savetime = 1;
}
if((t_1ms - scantime) < 0) //防止定时寄存器溢出时出现负数的情况
scantime = t_1ms;
if(savetime && t_1ms - scantime > 5) //5ms等待延时
reachtime = 1;
if(!reachtime)
goto Read__out;
//这一段设置了一个5ms的状态保持时间,在时间到了之后才会去读取W1-W4的状态
switch(switch_bite) //选择去拉低D0-D3中的哪一个
{
case 1: //操作D0
if(R_W) //决定是去拉低D0的电平,还是去读取W1的状态
{
//读取D0状态并写入暂存寄存器
if(P33)
Read_Switch[0] &= 0xEFFF;
else
Read_Switch[0] |= 0x1000;
if(P35)
Read_Switch[0] &= 0xFEFF;
else
Read_Switch[0] |= 0x100;
if(P36)
Read_Switch[0] &= 0xFFEF;
else
Read_Switch[0] |= 0x10;
if(P37)
Read_Switch[0] &= 0xFFFE;
else
Read_Switch[0] |= 0x1;
P15 = 1; //读取完成时重新拉高D0,以备下一次的读取
}else{
P15 = 0; //拉低D0
}
break;
case 2: //操作D1
if(R_W) //决定是去拉低D1的电平,还是去读取W2的状态
{
//读取D1状态并写入暂存寄存器
if(P33)
Read_Switch[0] &= 0xDFFF;
else
Read_Switch[0] |= 0x2000;
if(P35)
Read_Switch[0] &= 0xFDFF;
else
Read_Switch[0] |= 0x200;
if(P36)
Read_Switch[0] &= 0xFFDF;
else
Read_Switch[0] |= 0x20;
if(P37)
Read_Switch[0] &= 0xFFFD;
else
Read_Switch[0] |= 0x2;
P16 = 1; //读取完成时重新拉高D1,以备下一次的读取
}else{
P16 = 0; //拉低D1
}
break;
case 3: //操作D2
if(R_W) //决定是去拉低D2的电平,还是去读取W3的状态
{
//读取D2状态并写入暂存寄存器
if(P33)
Read_Switch[0] &= 0xBFFF;
else
Read_Switch[0] |= 0x4000;
if(P35)
Read_Switch[0] &= 0xFBFF;
else
Read_Switch[0] |= 0x400;
if(P36)
Read_Switch[0] &= 0xFFBF;
else
Read_Switch[0] |= 0x40;
if(P37)
Read_Switch[0] &= 0xFFFB;
else
Read_Switch[0] |= 0x4;
P17 = 1; //读取完成时重新拉高D2,以备下一次的读取
}else{
P17 = 0; //拉低D2
}
break;
case 4: //操作D3
if(R_W) //决定是去拉低D3的电平,还是去读取W4的状态
{
//读取D3状态并写入暂存寄存器
if(P33)
Read_Switch[0] &= 0x7FFF;
else
Read_Switch[0] |= 0x8000;
if(P35)
Read_Switch[0] &= 0xF7FF;
else
Read_Switch[0] |= 0x800;
if(P36)
Read_Switch[0] &= 0xFF7F;
else
Read_Switch[0] |= 0x80;
if(P37)
Read_Switch[0] &= 0xFFF7;
else
Read_Switch[0] |= 0x8;
P32 = 1; //读取完成时重新拉高D3,以备下一次的读取
}else{
P32 = 0; //拉低D3
}
break;
}
savetime = 0; //5ms定时时间到后的操作完成,等待下一次5ms定时
reachtime = 0; //重置定时标志
R_W = ~R_W; //拉低D0-D3或读取W1-W4标志转换
if(!R_W)
switch_bite++; //D0-D3循环
if(switch_bite > 4) //D0-D3全部读取完成进行数据处理,把十六进制值转换为我们设置的十进制值
{
switch_bite = 1;
Read_Switch_Dec[0] = 0;
turnchartmp[0] = Read_Switch[0];
for(i = 0; i < 4; i++)
{
switch(i)
{
case 0:
turnmul = 1;
break;
case 1:
turnmul = 10;
break;
case 2:
turnmul = 100;
break;
case 3:
turnmul = 1000;
break;
}
turnchar = turnchartmp[0] & 0xF;
Read_Switch_Dec[0] = Read_Switch_Dec[0] + turnchar * turnmul;
turncnt = (i + 1) * 4;
turnchartmp[0] = Read_Switch[0] >> turncnt;
}
turnchartmp[0] = Read_Switch[0];
}
Read__out:
_nop_();
}
- 上一篇: 微信视频号,最后的风口
- 下一篇: 加工中心PMC编程实用案例4:手轮倍率
猜你喜欢
- 2024-12-08 我用Python的Seaborn库,绘制了17个超好看图表
- 2024-12-08 让人抓狂的游戏迷宫,锁妖塔、神魔之井、草海曾让我有轻生的念头
- 2024-12-08 分析 Android 耗电原理后,飞书是这样做耗电治理的
- 2024-12-08 有了这些库,Android 开发效率提升好几倍
- 2024-12-08 在PieChart中间添加不同颜色不同大小的文字
- 2024-12-08 加工中心PMC编程实用案例4:手轮倍率
- 2024-12-08 微信视频号,最后的风口
- 2024-12-08 又发现3个超好用的抠图神器!完全免费无需注册,打开就能用
- 2024-12-08 3分钟学会程序员“面试回答规范”,不怕找不到工作的里面请
- 2024-12-08 潍坊一高校连续五年摘得国赛“移动互联网应用软件开发”金牌
- 最近发表
- 标签列表
-
- cmd/c (90)
- c++中::是什么意思 (84)
- 标签用于 (71)
- 主键只能有一个吗 (77)
- c#console.writeline不显示 (95)
- pythoncase语句 (88)
- es6includes (74)
- sqlset (76)
- apt-getinstall-y (100)
- node_modules怎么生成 (87)
- chromepost (71)
- flexdirection (73)
- c++int转char (80)
- mysqlany_value (79)
- static函数和普通函数 (84)
- el-date-picker开始日期早于结束日期 (76)
- js判断是否是json字符串 (75)
- c语言min函数头文件 (77)
- asynccallback (87)
- localstorage.removeitem (74)
- vector线程安全吗 (70)
- java (73)
- js数组插入 (83)
- mac安装java (72)
- 无效的列索引 (74)