AVR单片机串口USART与PC通讯实例和中断程序分析.docx

上传人:b****4 文档编号:4883348 上传时间:2022-12-11 格式:DOCX 页数:11 大小:275.80KB
下载 相关 举报
AVR单片机串口USART与PC通讯实例和中断程序分析.docx_第1页
第1页 / 共11页
AVR单片机串口USART与PC通讯实例和中断程序分析.docx_第2页
第2页 / 共11页
AVR单片机串口USART与PC通讯实例和中断程序分析.docx_第3页
第3页 / 共11页
AVR单片机串口USART与PC通讯实例和中断程序分析.docx_第4页
第4页 / 共11页
AVR单片机串口USART与PC通讯实例和中断程序分析.docx_第5页
第5页 / 共11页
点击查看更多>>
下载资源
资源描述

AVR单片机串口USART与PC通讯实例和中断程序分析.docx

《AVR单片机串口USART与PC通讯实例和中断程序分析.docx》由会员分享,可在线阅读,更多相关《AVR单片机串口USART与PC通讯实例和中断程序分析.docx(11页珍藏版)》请在冰豆网上搜索。

AVR单片机串口USART与PC通讯实例和中断程序分析.docx

AVR单片机串口USART与PC通讯实例和中断程序分析

 “并行”通讯:

是指8位数据同时通过并行线进行传送,这样数据传送速度大大提高,但并行传送的线路长度受到限制,因为长度增加,干扰就会增加,数据也就容易出错。

“串行”通讯:

形容一下就是一条车道,而并口就是有8个车道同一时刻能传送8位(一个字节)数据。

但是并不是并口快,由于8位通道之间的互相干扰。

传输时速度就受到了限制。

而且当传输出错时,要同时重新传8个位的数据。

串口没有干扰,传输重发一位就可以了。

所以要比并口快。

      串行通讯协议较多,单片机常用的有USART,SPI,TWI,1-Wire等。

串行通讯有分为同步和异步通讯:

通俗讲 同步就是你叫我去吃饭,我听到了就和你去吃饭;如果没有听到,你就不停的叫,直到我告诉你听到了,才一起去吃饭。

异步就是你叫我,然后自己去吃饭,我得到消息后可能立即走,也可能等到下班才去吃饭。

  同步通讯:

收信发信双方在使用同步时钟,在同一时刻传输线上的数据就是要传输的信息。

  异步通讯:

以字符为传输单位,字符与字符之间是异步的,而字符的位是同步的

USART:

异步串行通讯,常用与单片机和单片机,单片机和PC电脑间的数据传输。

波特率:

表征通讯速度的参数,单位是位/秒(b/s),即每秒钟传输的二进制位数,如波特率9600,表示每秒钟传输9600个二进制位数据。

收发双方必须采用同样的波特率。

波特率不同将无法正常通讯。

 

 全双工通讯:

指是的是可以同时发送和接收数据。

 半双工通讯:

指的是在同一时刻只能发送或只能接收数据。

单片机与PC通讯的电平转换:

单片机的电压一般是TTL电平,电压0v-5v,PC机串口采用的是RS-232协议,它的的电压范围是-15-+15v,电平不同,无法通讯。

要实现通讯,必须进行电平和逻辑关系的转换, 一般用 MAX232集成芯片进行电平的转换。

ATmega16串口结构:

有一个全双工的串行口,有两条通讯线,TXD:

数据发送线,RXD:

数据接收线,对应的单片机外部引脚为PD1,PD0

               相关寄存器:

UDR       串口数据寄存器,

                                   UCSRA   串口控制与状态寄存器A

                                   UCSRB   串口控制与状态寄存器B

                                    UCSRC 串口控制与状态寄存器C

UBRRH,UBRRL波特率寄存器

发生器对波特率发生器的输出时钟进行2、8或16的分频,具体情况取决于工作模式,如下图:

 

如:

系统时钟频率f=8MHZ,异步正常模式(16分频),波特率9600

    则:

UBRR=8000000/16*9600-1=52-1=51;  波特率寄存器赋值:

UBRRH=0; UBRRL=51;/*10进制写法*/,

或者UBRRH=0;UBRRL=0x33;/*16进制写法*/

操作步骤:

      一、设置异步模式:

UCSRC|=(1<

    二、设置数据帧格式:

 8位数据位,一位停止位,UCSRC|=(1<

    三、设置波特率寄存器:

UBRRL=51;UBRRH=0;

    四、使能发送接收:

        UCSRB|=(1<

    五、中断总使能:

 SREG=0X80;

//函数功能:

通过PC串口向单片发送数据,单片机接收数据后,送到PA口显示,再送回到PC机

#include

#include

#definefosc8000000 //晶振8MHZ

#definebaud9600    //波特率定义

/*端口初始化函数*/

void init(void)

{

 PORTA=0xFF;  //PA口输出高电平

 DDRA =0xFF;  //PA口设置为输出

 PORTD=0X00;      //USART的发送接收端口分别为PD0和PD1

 DDRD|=(1<

}

/*串口初始化函数*/

voiduart_init(void)

{

 UCSRB=0x00;

 UCSRA=0x00;

 UCSRC|=(1<

//UCSRC寄存器与UBRRH寄存器共用相同的I/O地址,写UCSRC时,URSEL应设置为1。

 UBRRL=51;     //设置波特率寄存器10进制的写法

 UBRRH=0;

 UCSRB|=(1<

}

/*发送数据函数*/

voidsend(unsignedchari)

{

while(!

(UCSRA&(1<

UDR=i;

}

/*以下是接收数据函数*/

unsignedchar receive(void)

{

while(!

(UCSRA&(1<

returnUDR;

}

/*主函数*/

voidmain(void)

{

 unsignedchartemp;

 init();

 uart_init();

 while

(1)

 {

 temp=receive();   //接收数据

 PORTA=~temp;    //将接收的数据取反后送PA口显示   

 send(temp);    //向PC机发送数据

 }

}

 

 

1.范例描述

按下按键0,LED0亮。

直到松手,其他按键才能起作用

按下按键1,LED1亮。

其他按键随时都能起作用

按下按键2,LED0/1都熄灭。

直到松手,其他按键才能起作用

2.电路图设计:

.

4.代码设计与说明:

本程序简单的示范了如何使用ATMEGA16的外部中断

中断的设置

按键的简单延时防抖动

中断的嵌套

变量在中断中的应用---如果变量会在中断服务程序中被修改,须加volatile限定

本范例可直接使出厂状态的新M16芯片,无需对芯片的熔丝位进行配置。

出于简化程序考虑,各种数据没有对外输出,学习时建议使用JTAGICE硬件仿真器

关于外部中断作唤醒源的条件:

(将会在后面的电源管理和睡眠模式范例中应用)

而INT0和INT1的边沿触发中断只能在空闲模式起作用,即CLKI/O不停止

INT0和INT1的低电平中断,INT2在各种睡眠模式下都可以,因为这几种中断工作

于异步模式,不需要时钟驱动

官方的M16中文手册对外部中断的描叙存在多处错误,请参考英文原版。

*/

#include

#include

#include

#include

/*宏INTERRUPT的用法与SIGNAL类似,区别在于

SIGNAL执行时全局中断触发位被清除、其他中断被禁止

INTERRUPT执行时全局中断触发位被置位、其他中断可嵌套执行

中断服务程序的编写具有一定的格式,在不同编译环境下各不相同,在WINAVR(GCC)环境下有两种方式,分别是:

第一种中断服务程序的编写格式:

SIGNAL(中断向量名)

{

…//中断服务程序内容

}

第一种中断服务程序的编写格式:

ISR(中断向量名)

{

…//中断服务程序内容

}

在这两种方式中,需要分别添加头文件:

#include和#include

另外avr-libc提供两个API函数用于置位和清零全局中断触发位,它们是经常用到的。

分别是:

voidsei(void)和voidcli(void)由interrupt.h定义*/

//注:

内部函数_delay_ms()最高延时262.144mS@1MHz

/*该函数可以实现较精确的定时,但用JTAG仿真时较麻烦---会进入机器码窗口(Disassembeler)

.注意跳开该语段。

一旦JTAG仿真进入该内部函数语句,会变得像"死机"一样(其实在运行中),可以先[break],然后

在后面的C语句设[breakpoint],[RUN]跳过*/

//for()/while()语句计算延时时间较麻烦。

//为了使_delay_ms()函数的延时正确,须在makefile中设定F_CPU为实际的系统时钟频

//本范例为1MHz内部RC振荡器即F_CPU=1000000

/*

C:

\WinAVR\avr\include\avr\目录包括所有芯片的定义和其他头文件

其中iom16.h定义ATMEGA16芯片的特性(中断向量,寄存器,位定义...)

包括下面中断服务程序的常量SIG_INTERRUPTx,PORTx,GICR.....

*/

//管脚定义

#defineEXT_INT02//PD2按键0

#defineEXT_INT13//PD3按键1

#defineEXT_INT22//PB2按键2

#defineLED00//PB0

#defineLED11//PB1

#defineLED23//PB3

//宏定义

#defineLED0_ON()PORTB|=(1<

#defineLED0_OFF()PORTB&=~(1<

#defineLED1_ON()PORTB|=(1<

#defineLED1_OFF()PORTB&=~(1<

#defineLED2_ON()PORTB|=(1<

#defineLED2_OFF()PORTB&=~(1<

//51系列的高电平输出能力很弱,低电平也仅能点亮LED.所以常见输出低电平才灯亮的接法。

//AVR芯片的高低驱动能力都很强,甚至能推动8字数码管的公共极,怎么接都没问题。

//全局变量

#definehas_volatile1//这里是条件编译

//可以修改has_volatile=1或0来看程序运行的效果

#ifhas_volatile

volatileunsignedcharFLAG;//全局变量,会在中断服务程序中被修改,须加volatile限定

#else

unsignedcharFLAG;//全局变量.

#endif

//仿真时在watch窗口,监控这些变量。

SIGNAL(SIG_INTERRUPT0)//INT0中断服务程序

{

//硬件自动清除INTF0标志位

_delay_ms(10);//延时

if((PIND&(1<

LED0_ON();//点亮LED0

loop_until_bit_is_set(PIND,EXT_INT0);//等待按键释放(变为高电平)

_delay_ms(10);//延时按键释放时也会抖动。

//即使同时发生其它的中断事件,如果在这里把相应的中断标志位清除,那么该中断将

不能触发进入中断服务

/*注意

读端口用PINx

写端口用PORTx*/

}

INTERRUPT(SIG_INTERRUPT1)//INT1中断服务程序

{

//硬件自动清除INTF1标志位

//这里全局中断被打开,将允许其他中断嵌套执行

_delay_ms(10);

if((PIND&(1<

LED1_ON();//点亮LED1

loop_until_bit_is_set(PIND,EXT_INT1);

_delay_ms(10);

}

SIGNAL(SIG_INTERRUPT2)//INT2中断服务程序

{

//硬件自动清除INTF2标志位

_delay_ms(10);

if((PINB&(1<

{

LED0_OFF();//熄灭LED0

LED1_OFF();//熄灭LED1

}

loop_until_bit_is_set(PINB,EXT_INT2);

FLAG=!

FLAG;//修改全局变量

_delay_ms(100);

}

intmain(void)

{

//上电默认DDRx=0x00,PORTx=0x00输入,无上拉电阻

PORTA=0xFF;//不用的管脚使能内部上拉电阻。

PORTC=0xFF;

PORTD=0xFF;

DDRB=(1<

PORTB=~((1<

//外部中断INT0,1,2做按键输入,使能内部上拉,就可以不用外接电阻了

MCUCR=(1<

/*

ISCx1:

0=00INTx引脚为低电平时产生中断请求

ISCx1:

0=01INTx引脚上任意的逻辑电平变化都将引发中断

ISCx1:

0=10INTx引脚的下降沿产生中断请求

ISCx1:

0=11INTx引脚的上升沿产生中断请求

MCUCSR&=~(1<

/*ISC2=0INT2引脚的下降沿产生异步中断请求

ISC2=1INT2引脚的上升沿产生异步中断请求

GIFR=(1<

GICR=(1<

FLAG=0;

sei();//使能全局中断

while

(1)

{

while(FLAG==0);

LED2_ON();//如果FLAG不加volatile限定(即has_volatile=0),

//程序将永远都运行不到这里。

while(FLAG!

=0);

LED2_OFF();

}

}

程序运行效果

按下按键0,LED0亮。

直到松手,其他按键才能起作用

按下按键1,LED1亮。

其他按键随时都能起作用

按下按键2,LED0/1都熄灭。

直到松手,其他按键才能起作用

LED2是根据按键2的顺序来亮灭,松手后变换,前提是FLAG加了volatile限定

*/

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 求职职场 > 简历

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1