没有合适的资源?快使用搜索试试~ 我知道了~
AVR学习笔记二十、基于模数转换的AD键盘实验.docx
0 下载量 70 浏览量
2023-11-17
14:30:41
上传
评论
收藏 167KB DOCX 举报
温馨提示
试读
17页
AVR学习笔记二十、基于模数转换的AD键盘实验.docx
资源推荐
资源详情
资源评论
AVR 学习笔记二十、基于模数转换的 AD 键盘实验
20.1 实例功能
在前面的实例中我们已经学习了在单片机系统中检测矩阵按键的接口电路和程序设计。
但是矩阵式键盘仍然要占用不少 I/O 口资源,4X4 键盘就占用了 8 根 I/O 口线,那么有没
有更简单的办法,使用更少的 I/O 口资源检测更多的按键呢?
通过前面的学习,我们知道按键检测实际上是检测连接按键的端口的高低电平值,而我
们在前面的实例中只是简单的判断连接按键的端口的电平是高电平(+5V)还是低电平
(0V)。那么是否可以通过电平的微小变化来检测按键是否被按下呢?
在这个实验中,我们采用模数转换(AD)的方法来实现 1 个 I/O 口识别 16 个按键的实验,
本实例分为三个功能模块,分别描述如下:
● 单片机系统:利用 ATmega16 单片机与 AD 键盘电路实现 1 个 I/O 口的多按键识别。
● 外围电路:AD 键盘电路、串口电平转换电路。
● 软件程序:编写软件,实现 AD 键盘识别 16 个按键的程序。
通过本实例的学习,掌握以下内容:
● AD 键盘的电路设计和程序实现。
20.2 器件和原理
20.2.1 AD 键盘的工作原理
我们知道 AVR 单片机自带有内部模数转换(AD)电路,那么我们就利用 AVR 的这一特性
来实现利用一个 I/O 口检测 16 个按键的实验。
图 1 为一个 A/D 键盘的原理图,从图中可以看出,当不同的按键被按下时,ADC 端点处
的电压不同,通过判断不同的电压值就可以判断出是那个按键被按下。
AVR 单片机的 A/D 转换位数为 10 位,实际应用中我们只取高 8 位的值就可以分辨出 16
个按键。我们设定 AD 转换的参考电压为 VCC,这样 A/D 键盘识别准确度最高,并且能够识
别更多的按键。
图 1 A/D 键盘电路
20.2.2 A/D 键盘的缺陷
在实际应用中,我们是不可能得到准确的 A/D 转换值的,这是因为存在以下几种误差:
1)、对于同一点处的电压值,A/D 多次采样的结果不可能完全相同。
2)、电阻的误差。电阻值由于电阻的精度和环境温度的原因,误差较大,所以 A/D 键盘
各个按键点的分压不准确。
3)、为尽量减少误差,可以采取增加电阻精度、增加温度补偿等方法,另外在软件处理
时候要注意消除按键抖动等因素,还要对实际转换值和标准值给出误差补偿。
4)、如果按键按下,经过 A/D 转换,若实际转换值在允许误差范围之内(需要实际测量
各点电压,并计算各点电压平均值),则认为按键按下,否则程序不响应。
5)、实际试验过程中,还要考虑电阻的累积误差,选用精度越高的电阻,可分辨的按键
数目越多。
20.3 电路和连接
本实验主要有两部分电路模块组成:串口电平转换电路,A/D 键盘电路。串口电平转换电
路在前面的实例中我们已经做过介绍,在此不再重复。这里我们重点介绍一下 A/D 键盘电路。
实际试验中我们将图 1 中的 ADC 接点连接到单片机的 PA1 口,也就是 A/D 转换的 AD1 通道。
20.4 程序设计
1、程序功能
在本实例中,我们利用串口将 A/D 键盘中按下的按键的键码值发送到计算机,通过串口助
手观察实验结果。
2、函数说明
本实例主要有串口数据发送程序和 A/D 键盘识别程序,串口数据发送程序我们前面例子中
已经介绍过,本实例的程序中不再详细说明。
3、编程说明
使用 WINAVR 开发环境,使用的是外部 12M 的晶振,所以需要将 makefile 文件中的时钟
频率修改为 12M。另外在程序烧录到单片机的时候,熔丝位也要选择为外部 12M 晶振(注意是
晶振,不是外部振荡器,一定不要选择错了,否则会导致单片机不能再烧写程序)。
4、程序代码
/***********************************************
**** AVR A/D键盘范例 ***
**** MCU: ATmega16 ***
**** 作者: maweili ***
**** 编译器:WINAVR ***
**** ***
**** 2009.4.3 ***
***********************************************/
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h> //中断函数头文件
//常量声明
#define BAUD 9600 //波特率设置值
//全局变量声明
unsigned int ADData; //AD转换获得的数据
//函数声明
void Port_Init(void); //端口初始化配置
void Usart_Init(void); //USART寄存器设置
void AD_Init(void); //AD初始化
void Usart_PutChar(unsigned char cTXData); //字节发送函数
void Usart_PutString(unsigned char *pcString); // 字符串发送数据
unsigned int AD_GetData(void); //AD转换函数
void GetKey(void); //显示按键值
int main(void)
{
unsigned char Delay3s;
Port_Init();
Usart_Init();
AD_Init();
Usart_PutString("AD键盘测试程序");
//Usart_PutString("你按下的按键序号为:");
sei(); //使能全局中断
while(1)
{
ADData = AD_GetData(); //获得的AD值
if(ADData > 5) //判断是否有按键按下
{
_delay_ms(50); //按键消抖
if(ADData > 5)
{
GetKey(); //获取按键值
}
_delay_ms(200);
}
for(Delay3s = 0;Delay3s < 10;Delay3s++) //延时3S
{
_delay_ms(90);
}
}
}
//端口状态初始化设置函数
void Port_Init()
{
PORTA = 0X00;
DDRA = 0x00; //ADC通道设置为输入口,高阻态
}
//USART寄存器配置函数
void Usart_Init()
{
UCSRA = 0X00;
UCSRC |= (1<<URSEL) | (1 << UCSZ1) | (1 << UCSZ0); //异步,数据格式8,N,1
//UCSRC寄存器与UBRRH寄存器共用相同的I/O地址,写 UCSRC 时, URSEL 应设置为
1。
UBRRL = (F_CPU / BAUD / 16 - 1) % 256; //波特率设置
UBRRH = (F_CPU / BAUD / 16 - 1) / 256;
UCSRB |= (1 << RXCIE) | (1 << RXEN) | (1 << TXEN); //发送使能
}
//字节发送函数
void Usart_PutChar(unsigned char cTXData)
{
while( !(UCSRA & (1 << UDRE)) ); //只有数据寄存器为空时才能发送数据
UDR = cTXData; //发送数据送USART I/O数据寄存器-UDR
}
//接收中断函数
ISR(USART_RXC_vect )
{
unsigned char Rev;
Rev = UDR; //从USART I/O数据寄存器-UDR中读出数据
Usart_PutChar(Rev); //将接收到的数据发送
}
void Usart_PutString(unsigned char *pcString)
{
while (*pcString)
{
Usart_PutChar(*pcString++);
剩余16页未读,继续阅读
资源评论
猫一样的女子245
- 粉丝: 93
- 资源: 2万+
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功