天天看點

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