AVR USART串口使用范例
- 格式:doc
- 大小:41.00 KB
- 文档页数:4
//ATMEGA16的USART串口发送与接收数据示例程序,采取中断的方式//发送200个FF,接收数据显示在数码管上,接收数据格式如09//编译环境 ICCAVR//系统时钟7.3728MHZ,设置熔丝位为外部高频石英晶体振荡,启动时间4.1ms//作者:David//日期:2013.10.20//*********************************************************************** // 包含文件//***********************************************************************#include <iom16v.h>#include <macros.h>#include <string.h>#include <stdio.h>#include <signal.h> //中断信号头文件//*********************************************************************** // 定义变量区//*********************************************************************** #define CH451_RESET 0x0201 //复位#define CH451_LEFTMOV 0x0300 //设置移动方式-左移#define CH451_LEFTCYC 0x0301 //设置移动方式-左循#define CH451_RIGHTMOV 0x0302 //设置移动方式-右移#define CH451_RIGHTCYC 0x0303 //设置移动方式-右循#define CH451_SYSOFF 0x0400 //关显示、键盘、看门狗#define CH451_SYSON1 0x0401 //开显示#define CH451_SYSON2 0x0403 //开显示、键盘#define CH451_SYSON3 0x0407 //开显示、键盘、看门狗功能#define CH451_DSP 0x0500 //设置默认显示方式#define CH451_BCD 0x058f //设置BCD译码方式#define CH451_TWINKLE 0x0600 //设置闪烁控制#define CH451_DIG0 0x0800 //数码管位0显示#define CH451_DIG1 0x0900 //数码管位1显示#define CH451_DIG2 0x0a00 //数码管位2显示#define CH451_DIG3 0x0b00 //数码管位3显示#define CH451_DIG4 0x0c00 //数码管位4显示#define CH451_DIG5 0x0d00 //数码管位5显示#define CH451_DIG6 0x0e00 //数码管位6显示#define CH451_DIG7 0x0f00 //数码管位7显示#define l ed0 0x0000 //数码管位0显示的数据0#define l ed1 0x0001 //数码管位0显示的数据1#define l ed2 0x0002 //数码管位0显示的数据2#define l ed3 0x0003 //数码管位0显示的数据3#define l ed4 0x0004 //数码管位0显示的数据4#define l ed5 0x0005 //数码管位0显示的数据5#define l ed6 0x0006 //数码管位0显示的数据6#define l ed7 0x0007 //数码管位0显示的数据7#define l edno 0x0010 //数码管灭#define dclk0 PORTD &= ~(1 << PD6) //串行数据时钟,上升延激活#define dclk1 PORTD |= (1 << PD6)#define din0 PORTD &= ~(1 << PD5) //串行数据输出,接CH451的数据输入#define din1 PORTD |= (1 << PD5)#define load0 PORTD &= ~(1 << PD4) //串行命令加载,上升延激活#define load1 PORTD |= (1 << PD4)#define uchar unsigned char#define uint unsigned int#define ulong unsigned long#define fosc 7372800 //晶振频率#define baud 9600 //设置波特率的大小uint tx_count=200,tx_flag=0xff;uchar A1,A2,A3;uchar usart_tx_data;uchar usart_rx_data;uchar table[]={0x00,0x01,0x02,0x03,0x04,0x05,0x06, //显示用数据0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};//*************************************************************************// 初始化子程序//*************************************************************************void system_init(){PORTD=0x7F; //PD0设置为输入,PD1输出DDRD=0x72; //上拉电阻使能有效}void ch451_init() //先低后高,选择4线输入{din0;din1;}void usart_init(){UCSRB = 0x00;UCSRA=0x00; //单倍速模式UBRRL = (fosc/16/baud-1)%256; //写波特率的值UBRRH = (fosc/16/baud-1)/256;UCSRC=(1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0); //UCSRC=086;写UCSRC寄存器 //异步通信无校验,8位数据1位停止位UCSRB=0xF8; //接收中断和发送中断允许}//***********************************************************************// 延时程序////***********************************************************************void delay_1ms(void){unsigned int i;for(i = 1; i < (unsigned int)(1144 - 2); i++);}void delay_ms(unsigned int n){unsigned int i = 0;while(i < n){delay_1ms();i++;}}//*************************************************************************// 数据处理函数//*************************************************************************void data_do(uchar temp_d){uchar A2t;A1=temp_d/100; //分出百,十,和个位A2t=temp_d%100;A2=A2t/10;A3=A2t%10;}//*************************************************************************// 串口相关中断服务子程序//************************************************************************* /* //数据发送结束中断向量#pragma interrupt_handler USART_TXC:14void USART_TXC() //中断服务程序{delay_ms(10); //相关操作}*///数据接收结束中断向量#pragma interrupt_handler USART_RXC:12void USART_RXC() //中断服务程序{CLI();//关中断usart_rx_data=UDR; //将接收到的数据取出data_do(usart_rx_data); //数据处理,得到个位十位百位SEI(); //开中断}/* //数据寄存器空中断向量#pragma interrupt_handler USART_UDRE:13void USART_UDRE() //中断服务程序{UDR=usart_tx_data; //发送数据到数据寄存器tx_count--;if(tx_count==0x00){tx_flag=0x01;}}*///************************************************************************* // 串口发送相关程序//************************************************************************* //发送单个字符void PutChar(char c){//PORTC |= (1 << PC3); //改变1487控制口为输出态,PC3=1 发送允许,接收禁止while(!(UCSRA & (1 << UDRE)));UDR = c;while(!(UCSRA&(1<<TXC)));UCSRA |= (1 <<TXC);//将发送结束标志位清零//PORTC &= ~(1 << PC3); //改变1487控制口为输出态,PC3=0 接收允许,发送禁止}//发送不带换行回车的字符串void PutNStr(unsigned char *Str){while (*Str != '\0'){PutChar(*Str);Str++;}}//发送带换行回车的字符串void PutStr(unsigned char *Str){while (*Str != '\0'){PutChar(*Str);Str++;}PutChar(0x0D);PutChar(0x0A);}//*************************************************************************// 输出命令子程序// 定义一无符号整型变量存储12字节的命令字//************************************************************************void ch451_write(unsigned int command){unsigned char i;load0; //命令开始for(i=0;i<12;i++){ //送入12位数据,低位在前if(command&1){din1;}elsedin0;dclk0;dclk1; //上升沿有效command>>=1;}load1; //加载数据}//*************************************************************************// 显示函数//*************************************************************************void display(uchar b_data,uchar s_data,uchar g_data){system_init();ch451_init();ch451_write(CH451_SYSOFF); //关显示、键盘、看门狗ch451_write(CH451_SYSON1); //开显示ch451_write(CH451_BCD); //设置BCD译码方式ch451_write(CH451_TWINKLE); //设置闪烁控制ch451_write(CH451_DIG0|table[b_data]); //显示接收到的值ch451_write(CH451_DIG1|table[s_data]);ch451_write(CH451_DIG2|table[g_data]);ch451_write(CH451_DIG3|ledno);ch451_write(CH451_DIG4|ledno);ch451_write(CH451_DIG5|ledno);ch451_write(CH451_DIG6|ledno);ch451_write(CH451_DIG7|ledno);}//*************************************************************************// 主程序//*************************************************************************void main(){system_init(); //系统初始化usart_init(); //usart串口初始化配置//usart_tx_data=0xff;SREG|=0x80; //开启全局中断while(1){/*while(tx_flag!=0x01) //数据发送是否完成,也可用发送完成中断 {//usart_tx_data=0xff;PutChar(0xFF);tx_count--;if(tx_count==0x00){tx_flag=0x01;}//delay_ms(10);}*///UCSRB=0xF0;display(A1,A2,A3); //显示接收到的数据 }}。
基于A VR单片机USART与PC机的串行通信
PC机发送字符给单片机控制发光管亮,同时将其传回PC机,其中单片机的发送和接收都采用查询方式
1、USART的主要特点
通用同步和异步串行接收器和转发器(USART)是一个高度灵活的串行通讯设备。
主要特点为:
全双工操作(独立的串行接收和发送寄存器)
异步或同步操作
主机或从机提供时钟的同步操作
高精度的波特率发生器
支持5,6,7,8,或9 个数据位和1 个或2 个停止位
支持的奇偶校验操作
数据过速检测?帧错误检测
噪声滤波,包括错误的起始位检测,以及数字低通滤波器三个独立的中断:发送结束中断,发送数据寄存器空中断,以及接收结束中断
多处理器通讯模式
倍速异步通讯模式
2、异步串行收发器
USART 分为了三个主要部分:时钟发生器,发送器和接收器。
控制寄存器由三个单元共享。
时钟发生器包含同步逻辑,通过它将波特率发生器及为从机同步操作所使用的外部输入时钟同步起来。
XCK (发送器时钟)引脚只用于同步传输模式。
发送器包括一个写缓冲器,串行移位寄存器,奇偶发生器以及处理不同的帧格式所需的控制逻辑。
写缓冲器可以保持连续发送数据而不会在数据帧之间引入延迟。
由于接收器具有时钟和数据恢复单元,它是USART 模块中最复杂的。
恢复单元用于异步数据的接收。
除了恢复单元,接收器还包括奇偶校验,控制逻辑,移位寄存器和一个两级接收缓冲器UDR。
接收器支持与。
AVR单片机学习(七)异步串行口UART 串行通讯技术概述异步串行通讯原理UART与电脑的通讯M16的USART中断方式使用USART步骤一、串行通讯技术概述串行通讯的通俗定义:一位发送一位(相对与并行,)当然通过位同步帧同步串行通讯的分类同步串行通讯时钟线、数据线、通过时钟保持数据同步SPI,IIC属于同步串口通讯异步串口通信只有一根数据线,通过波特率保证数据同步(顾名思义没有时钟线只有数据线)UART无线通信一般均为异步串行通信(相对于无形之中只能有一根天线)波特率每秒发送码元时间宽度为(1/9600)S大概是在100个微妙左右发送方按照波特率发出数据接收方按照波特率确定码元时间宽度对数据进行采样帧格式8位数据格式idle 空闲时候保持高电平在发送数据的时候先发送一位起始位低电平0然后数据 0 1 。
8 位P这位是可选的一般在多级通讯的时候需要发送9位数据在第9位时候是地址位SP1(必选的一位停止位是1)也可以选2位加一个SP2但是一般都是1位起始位 1位停止位 8位数据位之后数据继续保持空闲高电平接线图发送端:TXD接收端:RXD交叉连接RS232电平标准逻辑1 :-15V逻辑0 :+15VDB9 接口定义TXD/RXD/GDN三根线即可瞒足绝大数应用场合下面是开发板电路图MAX3232标示的是3.3V的芯片我们用的是5V MAX232 芯片标示错了不论引脚封装还是顺序都是完全相同的。
MAX 232芯片能提供2路串口我们只用一个。
由于这个电路图上是按照DB9定义的走线了所以我们就得用交叉线来跟PC 通讯了。
M16的USART特点全双工操作(独立的串行接受合发送寄存器,不像51是公用同一个寄存器,只能半双工)异步或同步操作(当然同步一般用不到。
所以我们只当异步串行口使用)支持5,6,7,8或9个数据位和1个或2个停止位(一般用的最多是8位数据 1位停止)硬件支持的奇偶校验操作(一般用不到,有限的场合通信质量还是可靠的,没必要加上校验)三个独立的中断源(看技术文档《一》)噪声滤波,包括错误的起始位检测,以及数字低通滤波器USART寄存器universal(通用的大体的)synchronous(同步) asynchronous(异步)R/T(接受/发送)UDRUCSRAUCSRBUCSRCUBRRL与UBRRH《一》Three Separate Interrupts (3个分离独立的中断 ) TXcomplete 发送完成中断,TX Data Register Empty 发送数据寄存器空中断RX Complete 接受完成中断。
AVR通过串口给芯片烧录程序(ATMega16)AVR通过串口给芯片烧录程序(ATMega16)相信大家都用过STC系列的51单片机,STC系列的单片机烧录程序都很简单,只需要通过串口就可以实现程序的烧录。
于是就想让avr 的芯片也能实现通过串口就能下载的功能,这样就可以省去购买usbasp下载线或者高压编程器的费用了。
仔细研究avr的芯片手册,发现都是带有bootloader功能,同时这个bootloader功能可以读写芯片的整个flash存储区,并且包括bootloader区,而且还有另外一个特点:如果bootloader功能开启以后,每次复位都会从bootloader启动。
接下来再来研究一下STC芯片的烧录功能:当在烧录软件中按下“下载”按钮以后,烧录软件会通过传给给STC芯片不停的发送一串数据,此时给STC芯片下电,然后上电,芯片上电以后,首先检测是否有烧录的请求,如果有就开始烧录程序,如果没有就开始执行芯片flash中的程序。
于是就有一个大概的思路了,可以给avr的芯片写一个bootloader的串口通信的程序,首先检测是否有烧录请求,如果有就更新flash中的程序,如果没有烧录请求,则执行flash中原有的程序。
经过几天的努力这个通过串口给atmega16烧录程序的固件和上位机终于完成了,为了方便大家这里共享处原理图和固件程序。
其实这种功能应该有人已经实现了,至少国外的开源硬件arduino就是通过这种方式给atmega8烧录程序的,但是atmega16我没有找到现成的,于是就自己实现了一个。
烧录软件使用winavr中的avrdude程序。
这也是一个开源项目,avrdude是一个控制台程序,操作不是很方便,于是写了一个应用程序封装了一下。
原理图:原理图实际上就是一个带有串口的avr最小系统。
烧录bootloader程序:下载ATMega16串口下载.rar 安装包,解压到本地目录,使用usbasp把“bootloader" 文件夹下的固件烧录到atmega16里,然后修改熔丝位:验证烧录程序:把自制的板子通过串口和电脑相连,运行“AvrSelfProgram.exe” 程序:在软件中选择正确的串口,并浏览打开要烧录的hex固件,此时按下板子上的复位按钮,然后点击“写FLASH”按钮。
“并行”通讯:是指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 串口控制与状态寄存器AUCSRB 串口控制与状态寄存器BUCSRC 串口控制与状态寄存器CUBRRH,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<<URSEL)|(1<<URMEL); //UCSRC和UBRRH寄存器共用一个地址,写UCSRC时,URSEL应置1二、设置数据帧格式: 8位数据位,一位停止位,UCSRC|=(1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);三、设置波特率寄存器:UBRRL=51;UBRRH=0;四、使能发送接收:UCSRB|=(1<<TXEN)|(1<<RXEN);五、中断总使能:SREG=0X80;//函数功能:通过PC 串口向单片发送数据,单片机接收数据后,送到PA口显示,再送回到PC机#include<iom16v.h>#include<macros.h>#define fosc 8000000 //晶振8MHZ#define baud 9600 //波特率定义/*端口初始化函数*/void init(void){PORTA = 0xFF; //PA口输出高电平DDRA = 0xFF; //PA口设置为输出PORTD = 0X00; //USART的发送接收端口分别为PD0和PD1DDRD|=(1<<PD1); //PD0为接收端口置为输入;PD1为发送端口置为输出}/*串口初始化函数*/void uart_init(void){UCSRB = 0x00;UCSRA = 0x00;UCSRC |= (1<<URSEL)|(1 << UCSZ1)|(1 << UCSZ0); //异步,数据格式8,N,1//UCSRC寄存器与UBRRH寄存器共用相同的I/O地址,写UCSRC时,URSEL应设置为1。
avr单片机USART串口通讯初始化配置说明avr atmega16 单片机通用同步和异步串行接收器和转发器(USART)是一个高度灵活的串行通讯设备,其工作模式及其初始化,寄存器说明如下。
//*******************USART控制和状态寄存器A(UCSRA)*************** /*USART 控制和状态寄存器A(UCSRA)bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0RXC TXC UDRE FE DOR PE U2X MPCMRXC: USART 接收结束接收缓冲器中有未读出的数据时RXC 置位,否则清零。
接收器禁止时,接收缓冲器被刷新,导致RXC 清零。
RXC 标志可用来产生接收结束中断TXC: USART 发送结束发送移位缓冲器中的数据被送出,且当发送缓冲器(UDR) 为空时TXC 置位。
执行发送结束中断时TXC 标志自动清零,也可以通过写0进行清除操作。
TXC 标志可用来产生发送结束中断( 见对TXCIE 位的描述)。
UDRE: USART 数据寄存器空UDRE标志指出发送缓冲器(UDR)是否准备好接收新数据。
UDRE为1说明缓冲器为空,已准备好进行数据接收。
UDRE标志可用来产生数据寄存器空中断复位后UDRE 置位,表明发送器已经就绪。
FE: 帧错误如果接收缓冲器接收到的下一个字符有帧错误,即接收缓冲器中的下一个字符的第一个停止位为0,那么FE 置位。
这一位一直有效直到接收缓冲器(UDR) 被读取。
当接收到的停止位为1 时,FE 标志为0。
对UCSRA 进行写入时,这一位要写0。
DOR: 数据溢出数据溢出时DOR 置位。
当接收缓冲器满( 包含了两个数据),接收移位寄存器又有数据,若此时检测到一个新的起始位,数据溢出就产生了。
这一位一直有效直到接收缓冲器(UDR) 被读取。
对UCSRA 进行写入时,这一位要写0。
PE: 奇偶校验错误当奇偶校验使能(UPM1 1),且接收缓冲器中所接收到的下一个字符有奇偶校验错误时UPE 置位。
USART串口配置方法
一、USART串口概述
USART串口是一种典型的异步传输接口,它在通信双方之间没有时钟
信号,只通过特定的标志位来确定通信开始和结束,是一个非同步的接口。
USART串口能够实现两种不同的传输模式:点对点和点对多,它是最常用
的外设之一,可以把复杂的通信系统变得简单。
1.波特率配置:波特率是指每秒发送数据的比特数,配置USART串口
的波特率有两种方式,一种是使用USART串口的控制寄存器中的可编程波
特率位定时器(BRG)来配置,另一种是使用专门为USART串口设计的波
特率设置程序。
2.数据格式配置:数据格式是指USART的数据格式,即数据的位长、
停止位、奇偶校验等,这些参数都是在控制寄存器中进行配置的,我们可
以根据自己的应用程序来配置。
3.中断配置:USART串口也有很多的中断,我们可以选择性地使能这
些中断,从而实现更好的数据传送效率,灵活控制通信状态。
4.其他硬件配置:USART串口还有其他的硬件配置,例如发送和接收
中断允许位、多处理器通信模式等等。
/*
A VR USART串口使用范例
编译器:WinA VR-20050214
本程序简单的示范了如何使用ATMEGA16的USART
USART的设置
波特率的计算
发送采用查询方式
接收采用中断方式
*/
#include <avr/io.h>
#include <avr/delay.h>
#include <avr/signal.h>
#include <avr/interrupt.h>
/*
注:本范例为7.3728MHz外部石英晶体振荡器即F_CPU=7372800
因为7.3728MHz能生成多种标准的通讯波特率
如果使用其他系统时钟频率,注意波特率误差不要超过+/-1%.
做USART通讯时,除非你掌握了校准技术,否则请不要使用内部/外部RC振荡器
*/
//管脚定义
#define PIN_RXD 0 //PD0 RXD
#define PIN_TXD 1 //PD1 TXD
#define LED0 0 //PA0
#define LED1 1 //PA1
#define LED2 3 //PA3
//常量定义
#define BAUDRATE 9600 //波特率
//#define F_CPU 7372800 //这个已经在makefile里面定义了
//宏定义
#define LED0_ON() PORTA&=~(1<<LED0) //输出低电平,灯亮
#define LED0_OFF() PORTA|= (1<<LED0) //输出高电平,灯灭
#define LED1_ON() PORTA&=~(1<<LED1)
#define LED1_OFF() PORTA|= (1<<LED1)
#define LED2_ON() PORTA&=~(1<<LED2)
#define LED2_OFF() PORTA|= (1<<LED2)
//51系列高电平输出能力很弱,低电平也仅能点亮LED,所以常见输出低电平才灯亮的接法//A VR芯片的高低驱动能力都很强,甚至能推动8字数码管的公共极,怎么接都没问题
//全局变量如果变量会在中断服务程序中被修改,须加volatile限定
volatile unsigned char FLAG; //按键标志
volatile unsigned char PC_COMMAND; //PC发出的当前命令
volatile unsigned char RX_BUFFER[16]; //存放接收数据的数组
volatile unsigned char RX_index; //存放接收数据的个数
void put_c(unsigned char c) //发送采用查询方式
{
while( !(UCSRA & (1<<UDRE)) ); //等待发送缓冲器为空
UDR=c; //将数据放入缓冲器,发送数据
}
void put_s(unsigned char *ptr)
{
while (*ptr)
{
put_c(*ptr++);
}
put_c(0x0D);
put_c(0x0A); //结尾发送回车换行
}
SIGNAL(SIG_USART_RECV) //串口接收中断服务程序
{
PC_COMMAND=UDR; //发送数据缓冲寄存器和接收数据缓冲寄存器共享地址,即UDR switch(PC_COMMAND)
{
case '0': //0x30 ASCII '0'
LED0_ON();
put_s("用户输入0#指令");
break;
case '1':
LED1_ON();
put_s("用户输入1#指令");
break;
case '2':
LED0_OFF();
LED1_OFF();
FLAG=!FLAG;
put_s("用户输入2#指令");
break;
default:
put_s("用户输入的指令无效!");
break;
}
/*
注意:使用put_s函数发送数据需要一定的时间,如果输入数据的速度过高将会导致
数据丢失,所以一般建议中断服务程序的处理时间尽量的短,只做采集数据和设标
志位,命令的处理交由主程序来完成,这里只是示范简单的命令处理*/
RX_BUFFER[RX_index]=PC_COMMAND; //保存数据到数组里面
RX_index++;
if (RX_index>=16) RX_index=0; //防止数组溢出
}
void init_USART(void) //USART初始化
// 9600 8, n,1 PC上位机软件(超级终端等)也要设成同样的设置才能通讯
{
UCSRC = (1<<URSEL) | 0x06;
//异步,8位数据,无奇偶校验,一个停止位,无倍速,10000110
/*
UBRRH与UCSRC共用I/O 地址。
因此访问该地址时需注意以下问题:
当在该地址执行写访问时,USAR寄存器选择位(URSEL)控制被写入的寄存器,若URSEL为0,对UBRRH值更新;若URSEL为1,则对UCSRC设置更新。
对UBRRH 或UCSRC 寄存器的读访问则较为复杂。
但在大多数应用中,基本不需要读这些寄存器。
没有UBRR这个16位寄存器,因为UBRRL(0x09)/UBRRH(0x20)的地址不连续,而且UBRRH 跟UCSRC共用地址
*/
//U2X=0时的公式计算
UBRRL= (F_CPU/BAUDRATE/16-1)%256;
UBRRH= (F_CPU/BAUDRATE/16-1)/256;
//U2X=1时的公式计算
//UBRRL= (F_CPU/BAUDRATE/8-1)%256;
//UBRRH= (F_CPU/BAUDRATE/8-1)/256;
//也可根据数据手册的[波特率设置的例子]查得: UBRR = 47
//UBRRL = 0x2F; //set baud rate lo
//UBRRH = 0x00; //set baud rate hi
UCSRA = 0x00;
UCSRB = (1<<RXCIE)|(1<<RXEN)|(1<<TXEN);//使能接收中断,使能接收,使能发送}
void pro_coammand(void) //多字节命令的处理程序
{
unsigned char i;
if (RX_index>=10)
{
UCSRB&= ~(1<<RXCIE); //关断USART接收中断
put_c(0x0D);
put_c(0x0A); //发送回车换行
put_s("Hello!你之前输入的命令列表是:");
for (i=0;i<RX_index;i++) put_c(RX_BUFFER[i]);
put_c(0x0D);
put_c(0x0A); //发送回车换行
RX_index=0; //清零
UCSRB|= (1<<RXCIE); //打开USART接收中断
}
}
int main(void)
{
//上电默认DDRx=0x00,PORTx=0x00 输入,无上拉电阻
PORTB =0xFF; //不用的管脚使能内部上拉电阻PORTC =0xFF;
DDRA =(1<<LED2)|(1<<LED1)|(1<<LED0); //输出
PORTA =((1<<LED2)|(1<<LED1)|(1<<LED0)); //高电平,灯灭
DDRD =(1<<PIN_TXD); //TXD为输出
PORTD =0xFF;
FLAG=0;
init_USART();
put_s("你好!");
put_s("这是一个简单的串口实验程序");
put_s("你可以在电脑上的超级终端程按下[0][1][2]按键,模拟用户板上的按键操作");
sei(); //使能全局中断
while (1)
{
while (FLAG==0) pro_coammand();
LED2_ON();
//如果FLAG不加volatile限定(即has_volatile=0),程序将永远都运行不到这里
while (FLAG!=0) pro_coammand();
LED2_OFF();
}
}。