AVR单片机串口USART与PC通讯实例和中断程序分析.docx
- 文档编号:4883348
- 上传时间:2022-12-11
- 格式:DOCX
- 页数:11
- 大小:275.80KB
AVR单片机串口USART与PC通讯实例和中断程序分析.docx
《AVR单片机串口USART与PC通讯实例和中断程序分析.docx》由会员分享,可在线阅读,更多相关《AVR单片机串口USART与PC通讯实例和中断程序分析.docx(11页珍藏版)》请在冰豆网上搜索。
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 另外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限定 */
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- AVR 单片机 串口 USART PC 通讯 实例 中断 程序 分析
![提示](https://static.bdocx.com/images/bang_tan.gif)