|
不知不觉我们已经走过了七站了,今天我们开始我们的第八站:Atmega128单片机扩展拔码开关的使用。
在我们学习Atmega128单片机控制拔码开关之前,首先给大家普及下拔码开关的基础知识。
何为拔码开关?
拨码开关(也叫DIP开关,拨动开关,超频开关,地址开关,拨拉开关,数码开关,指拨开关)是一款用来操作控制的地址开关,采用的是0/1的二进制编码原理。通俗的说也就是一款能用手拨动的微型的开关,所以也通常叫指拨开关的也很多。拔码开关是一种有通、断两种稳定状态的开关,可以看做是一种特殊的按键,但是使用方法和按键是类似的,区别就是,不会自动恢复到未接通时候的状态。
一般拔码开关2~8个做成一组,用来设置地址码,给大家展示一种拔码开关,如图1:
图1. 4位拔码开关
从上图1可以看到这个拔码开关,每一个键对应的背面上下各有两个引脚,拨至ON一侧,这下面两个引脚接通;反之则断开。这四个键是独立的,相互没有关联。此类元件多用于二进制编码。可以设接通为1;断开为0,则有:
0000
0001
0010
……
1110
1111
一共是16种编码
之所以给大家讲Atmega128单片机控制拔码开关,是因为我们在工作中,某一个项目工程可能会用到很多的Atmega128单片机或者其他单片机,为了区分他们,就需要给他们编号,也就是给地址码,这个地址码可以写在程序代码中,但写在程序代码中的地址码不可以修改,在使用过程中就不方便,于是有人就想到了一种可以用手随时改变地址码的方法,也就是拔码开关的应用。
本次实验使用一个8位的拔码开关来给Atmega128单片机设置地址码,然后用数码管将这个地址码显示出来。我们知道8位拔码开关可以设“0000~0xFF”共256个地址码,好了现在开始设计电路,电路图如下图2:
图2. Atmega128单片机扩展拔码开关电路图
8位拔码开关连接到Atmega128单片机的PA端口,4位共阴极数码管的数据端连接在Atmega128单片机的PE端口上,控制引脚连接在PF0~PF3上。
我们来构思下程序代码的思路:
此程序包含以下几大点:
1、既然用到了数码管,就需要有数码管显示的字符编码,并且有数码管显示的函数,这个原理和代码我们在之前已经学习过了,我们通过一个子函数的形式被主函数调用来实现。
2、我们需要一个函数来读取拔码开关当前的地址码,然后把读取的地址码转换成十进制数字,为显示函数做好基础。
3、再通过一个显示的函数来显示这个地址码,并通过数码管显示。
整理好思路,我们就来编代码吧:
#include<iom128v.h>
const unsigned char Dsy_index[]={0x08;0x04;0x02;0x01;0x80;0x40;0x20;0x10};
unsigned char Dsy_buf[]={16,16,16};
const unsigned char Dsy_code_cn[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x40,0x00};
unsigned char Key_code;
void delay_ms(uint ms)
{
uint i,j;
for( i=0;i<ms;i++)
for(j=0;j<1141;j++);
}
void Port_init(void)
{
DDRA=0x00;
PORTA=oxFF;
DDRE=0xFF;
PORTE=0xFF;
DDRF=0xFF;
PORTF=0xFF
}
unsigned char Key_scan()
{
if(PINA!=Key_code)
{
delay_ms(10);
if(PINA!=Key_code)
{
Key_code=PINA;
}
}
return Key_code;
}
void Num_dsy(unsigned char num)
{
unsigned char i,j;
Dsy_buf[0]=num/100;
Dsy_buf[1]=num/10;
Dsy_buf[2]=num;
for(i=0;i<3;i++)
{
PORTE=Dsy_code_cn[Dsy_buf]; PORTF=~Dsy_index[3-i]; delay_ms(10); PORTF=0xFF; }}
void main(void){ Port_init(); PORTC=0xEF; while(1) { Num_dsy(Key_scan());
}}
针对函数给大家基本解读一下:
const unsigned char Dsy_index[]={0x08;0x04;0x02;0x01;0x80;0x40;0x20;0x10};
unsigned char Dsy_buf[]={16,16,16};
const unsigned char Dsy_code_cn[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x40,0x00}; unsigned char Key_code;
函数在最初对 Dsy_index[],Dsy_buf[],Dsy_code_cn[] 和Key_code进行了声明,Dsy_index[]是用来放数码管位选信号的,Dsy_buf[]是一个code 空间的缓冲区,可以用来暂时存放数码管显示字形编码,可以被后面程序调用。Dsy_code_cn[]这个就是数码管显示的字形编码,之前我们已经学习过了。Key_code用来存放我们设定的拔码开关的值,为程序中转换为10进制数准备。
void delay_ms(uint ms)
{
uint i,j;
for( i=0;i<ms;i++)
for(j=0;j<1141;j++);
}
毫无疑问,这个子函数就是延时子函数,用在程序中需要的延时,在我们这个程序中主要就是之前学习的延时消抖。
void Port_init(void)
{
DDRA=0x00;
PORTA=oxFF;
DDRE=0xFF;
PORTE=0xFF;
DDRF=0xFF;
PORTF=0xFF
}
这个是Atmega128单片机IO端口初始化子函数,在我们这个实例中,使用PA端口来获取拔码开关的值,所以PA口设置为输入,PE引脚和PF引脚分别用来控制显示数字和位选,所以设置为输出。
unsigned char Key_scan()
{
if(PINA!=Key_code)
{
delay_ms(10);
if(PINA!=Key_code)
{
Key_code=PINA;
}
}
return Key_code;
}
此子函数是读取拔码开关子函数,最初先消抖,然后再把读取PINA的电平,也就是拔码开关的电平,获得拔码开关的0/1二进制值。
void Num_dsy(unsigned char num)
{
unsigned char i,j;
Dsy_buf[0]=num/100;
Dsy_buf[1]=num/10;
Dsy_buf[2]=num;
for(i=0;i<3;i++)
{
PORTE=Dsy_code_cn[Dsy_buf];
PORTF=~Dsy_index[3-i];
delay_ms(10);
PORTF=0xFF;
}
}
此函数是获取的拔码开关的0/1二进制数转换为10进制数,转换的数值暂时放在Dsy_buf[]进行缓存。
大家实验一下,随机设置一个拔码开关的数值,观察数码管是否正确的显示数字出来?
这个实例从另外一个方面跟我们日后要学习的DA转换很是想象,所以学好这个实例对我们日后的学习大有作用哦,学友们,你学会了吗?
本次的文章就到这,我们下期再见,感谢大家的观看,谢谢。 |
|