天天看点

Atmega128串口详解

Atmega128串口详解

Atmega128有两个串口:USART0与USART1

以USART0为例

串口的初始化包括:

传输模式的选择:同步还是异步,默认为异步模式,可通过选择USART控制和状态寄存器UCSR0C中的UMSEL位来选择,UMSEL为0,是异步模式.

波特率的设置:通信的双方都必须有相同的波特率,波特率可以通过设置波特率发生寄存器UBRR0来确定,UBRR0为两字节16位的寄存器,可分为 UBRR0H和UBRR0L.同时起作用的还有UCSR0A中的波特率加倍位UX2,当UX2为1时设置的波特率加倍.

传输帧格式的设置:默认是8位数据位,一位停止位

发送接受的使能与中断:通过设置UCSR0B来根据需要选择接收或发送的使能和是否使用中断,对使用中断的USART操作,初始化前要关闭中断

USART0的控制和状态寄存器有:UCSR0A,UCSR0B,UCSR0C,波特率寄存器有UBRR0,即UBRR0H和UBRR0L, 数据寄存器为UDR0 1、初始化:

设置波特率前,要关闭USART0的所有使用,包括使能和中断:

UCSR0B=0B00000000; //关闭USART0

2、设置UCSR0A:

UCSR0A能写的有Bit0,Bit1,Bit6,其他5位为状态位.我们一般使用的有Bit1-U2X0,当这一位为1时,波特率的分频因子从16降到8,能够有效的将异步通信模式的传输速率加倍,但是这一位仅对异步操作有影响,使用同步操作时应将此位清零.

UCSR0A=0B00000000; //不使用倍速发送

3、设置UCSR0C:

Bit6-UMSEL0:USART0的模式选择,0为异步模式,1为同步模式

Bit5:4-UPM01:0:奇偶校验模式,00禁止,01,保留,10偶校验,11,奇校验

Bit3-USBS0:停止位的选择,0停止位为1bit,1停止位为2-bits

Bit2:1-UCSZ01:0:字符长度,当UCSZ02为0时,00表示5位,01表示6位,10表示7位,11表示8位.当UCSZ02为1时,11表示9位.(UCSZ02为UCSR0B里的一位寄存器) eg:

UCSR0C=0B00000110 //异步模式,禁止奇偶校验,停止位为1位,数据位为8位

4、设置UBRR:

UBRR的设置和这些参数有关:U2X0,CPU频率,波特率

当U2X0为0时,即异步正常模式下,UBRR的计算公式:

1、U2X=0时的公式计算

UBRR0L= (F_CPU/BAUDRATE/16-1)%256;

UBRR0H= (F_CPU/BAUDRATE/16-1)/256;

2、U2X=1时的公式计算

UBRRL= (F_CPU/BAUDRATE/8-1)%256;

UBRRH= (F_CPU/BAUDRATE/8-1)/256;

//也可根据数据手册的[波特率设置的例子]查得

//UBRRL = 0x2F; //set baud rate lo

//UBRRH = 0x00; //set baud rate hi

设置一般会有误差,误差计算方法为: Error[%]=(BaudRate_ture/BaudRate-1)*100%;

5、然后就是设置UCSR0B:

Bit7-RXCIE0为接收结束中断使能,Bit6-TXCIE0为发送结束中断使能,Bit4-RXEN0为接收使能,Bit3-TXEN0为发送使能 .一般情况下,接收使用中断方式,所以使用接收结束中断使能.

UCSR0B=0B10011000 //发送接收使能,接收结束使能

还一种写法是UCSR0B|=(1<< RXEN0)|(1<< TXEN0)|(RXCIE0);

如果更熟练,可以直接以10进制活16进制来设置这些寄存器:

UCSR0B=0x98;或者UCSR0B=152; 串口的初始化函数: void uart_init(void) //串口0初始化

{

UCSR0B=0x00; //disable while setting baud rate

UCSR0A=0B00000000; //Bit1为1则倍速发送 U2X=0

UCSR0C=0x06; //B00000110 //奇偶模式无,八位数据位,一位停止位

UBRR0L=103; //B00011001波特率:9600 Bps

UBRR0H=0x00; //误差率:0.156%

UCSR0B=0x98;

} 初始化之后就是对USART0进行读写了.

UCSR0A的Bit5-UDRE0标志指出发送缓冲器UDR0是否准备好接收新数据,UDRE0为1说明缓冲器为空,可以接收新数据,UDRE0标志也可用来产生寄存器空中断.复位后的UDRE0置位,表明发送器已经就绪:

当UDRE0为1时!(UCSR0A&(1<< UDRE0))为0

void putchar(uchar c) //串口0发送字符

{

while(!(UCSR0A&(1<< UDRE0))); //while(!(UCSR0A&32)); 表明发送器已经就绪。

UDR0=c;

} 串口0发送字符串:

void putstr(uchar *s) //串口0发送字符串

{

while(*s)

{

putchar(*s);

s++;

}

} RXC0为UCSR0A里的Bit7位,为USART0接收结束的状态位, 接收缓冲器中有未读出的数据时RXC0置位,否则清零. 串口0接收字符:

uchar getchar(void) //串口0接收字符

{

while(!(UCSR0A&(1<< RXC0)));

return UDR0;

} 在使用串口的程序中一般包含这些文件:

#include 

#include 

#include 

#include 

avr/io.h里有各种寄存器的定义,avr/signal.h,avr/interrupt.h里有中断的定义,avr/delay.h包含延时函数. 例程: 串口通信(USART0)  

#include<iom128v.h>

#include<macros.h>

#define fosc 8000000  //晶振8MHZ

#define baud 2400  //波特率

void uart0_init(void)

{

 UCSR0B = 0x00;                     //关闭UART00

 UCSR0A = 0x00;                      //不使用倍速发送(异步)

 UCSR0C =(1<<UCSZ01)|(1<<UCSZ00);    //数据位为8位

 UBRR0L=(fosc/16/(baud+1))%256;      //异步正常情况下的计算公式

 UBRR0H=(fosc/16/(baud+1))/256;

 UCSR0B =(1<<RXEN0)|(1<<TXEN0);      //接收使能和发送使能

}

void putchar0(unsigned char c)

 {  

       while (!(UCSR0A&(1<<UDRE0)));//表明发送器已经准备就绪

    UDR0=c;    //将要发送的数据装入UDR0寄存器

 } 

unsigned char getchar0(void)

   {

    while(!(UCSR0A& (1<<RXC0)));//表明已经接收完毕

       return UDR0;

 }

void puts0(char *s)

 {

 while (*s)

  {

  putchar0(*s);

  s++;

  } 

    putchar0(0x0a);//回车换行

 //putchar0(0x0d);

 } 

void main(void)

{

 unsigned char i;   uart0_init();//UART0初始化

  puts0("HELLO!");  while(1)

    {    

        puts0("test ok!");        

 }

}      串口通信(USART1)

#include<iom128v.h>

#include<macros.h>

#define fosc 8000000  //晶振8MHZ

#define baud 9600  //波特率

void uart1_init(void) //USART1初始化

{

 UCSR1B = 0x00;   //关闭USART1

 UCSR1A = 0x00;   //不适使用倍速发送

 UCSR1C = (1<<UCSZ11)|(1<<UCSZ10);//数据位为八位

 UBRR1L=(fosc/16/(baud+1))%256;//异步正常模式下,UBRR的计算公式

 UBRR1H=(fosc/16/(baud+1))/256;

 UCSR1B =(1<<RXEN1)|(1<<TXEN1); //接收使能,传送使能

}

void putchar1(unsigned char c)//串口1发送字符

 {  

     while (!(UCSR1A&(1<<UDRE1)));//表明发送器一准备就绪

  UDR1=c;    

 } 

unsigned char getchar1(void) //串口1接回收数据

   {

  while(!(UCSR1A& (1<<RXC1)));

     return UDR1;   //将接收到的字符返回

 } 

void puts1(char *s)

 {

 while (*s)

  {

  putchar1(*s);

  s++;

  } 

        putchar1(0x0a);//回车换行

     putchar1(0x0d);

 } 

void main(void)

{

 unsigned char i;   uart1_init();

  puts1("HELLO!");  while(1)

    {    

        puts1("test ok!");        

 }

}  原文:http://blog.chinaunix.net/uid-21658993-id-1819999.html

avr