一.熟悉AVR單片機UART資源,首先從波特率和幀說起 波特率:與51不同有單獨的波特率發生器,不需要定時器來產生,節省了資源
波特率計算公式,這里我采用IccAVR的配置功能,直接計算生成
單片機支持的模式:異步正常模式,異步倍數模式,和同步模式,一般選第一種模式
幀格式:起始位+數據位(5-9位可選)+校驗位(可選)+停止位(1、2位) 空閑
o ********* P 1 1
通訊電路空閑時為高電平
本文引用地址:http://www.104case.com/article/201611/320644.htm二、大概了解了下硬件資源后,就要了解軟硬件的橋梁—寄存器了
1.數據寄存器:數據來了要有個接受的地方吧,數據發送要有個數據發送的信封吧。
這就是數據寄存器 UDR (RXB和TXB) 物理上為分開的,地址上是一樣的。就像寫信和接信時,你家的地址只
有同一個地址一樣,但是寫信和別人發給你的信封卻有2個一樣。使用時自動控制的。
數據寄存器為空時才能發送數據,否則會無效。數據進入后,進入移位寄存器,由引腳TXD一位位發出。
2.控制和狀態寄存器 UCSRA
RXC TXC UDRE FE DOR PE U2X MPCM
接受完成置1 發送完成置1 數據為空標志 幀錯誤1 接受數據 校驗位錯誤 倍速模式 多機通信
讀取數據清0 中斷時自動清0 數據完全到移 溢出1 1 1 地址位
位寄存器中1
UCSRB 設置相關中斷的允許
RXCIE TXCIE UDRIE RXEN TXEN UXSZ2 RXB8 TXB8
接受中斷允許 發送中斷允許 空中斷允許 數據接受允許 數據發送允許 位數設置 接受第9位
RXEN,TXEN設置時會改變時普通IO口,或者是當做復用口用,在發送數據時設置下,數據全部發送后才生效
RXB8,TXB8需要先讀寫出
UCSRC
URSEL UMSEL UPM1 UPM0 USBS UCSZ1 UCSZ0 UCPOL
寄存器選擇 工作模式 校驗方式 停止位 和上面的UXSZ2設置
寫時需要設為1 1異步 數據個數
存在共用寄存器 00禁止11奇10偶 0為1個1為2個
波特率寄存器:UBRRL UBRRH
UBRRH和UCSRC共用 了底4位 加上UBRRL共12位 設置后正在傳的數據會被打斷
需要注意URSEL的設置 :0 寫入的比特率高4位
1 寫入的是寄存器的內容
讀UBRRH,第一次是比特率的內容 在連續的2個時鐘周期內再讀一次就是UCRSC的內容
使用時可以查速查表,直接用ICCAVR生成工具即可。
三,相關操作 等練習個程序后補上
1 初始化 關全局中斷
TXC RXC看數據是否完成 發送數據前TXC必須請零
把數據放入到發送緩沖器即可 UDR中 5-8位
2 注意下空中斷 允許后需要不斷寫數據 否則一直不斷的中斷產生 一般禁止就可以了
TXEN 設置0后 所有數據發送后生效 然后就當普通IO口用了
禁止接受 會立即 丟失數據
四一些總線標準
RS232 9針D型接口
1 -3 ~-25 0 3-25V
需要使用電平轉換電路 MAX232
五.工業設計中的串口
這里如果大家看到了還是注意下比較好 ,網上寫的不多的,我也是從工程實踐和查找大量的參考書中總結的
設計思路是基于狀態機,并自定義了協議,同時協議中使用了CRC校驗,和簡易的加密技術
思路是:主從方式,上位機發送數據包,下位機在中斷中接受,接受數據時要一位位的確認,并不斷進行切換,發送的位置狀態,把初步確認的數據放到接受緩沖器里,等所有的數據接收好了,程序進入大循環了,就執行主程序中加入uart操作函數,這個函數首先判斷主機發送的命令和設置是否接受完成,在完成的狀態下進行校驗正確性,校驗后,根據主機命令,組裝數據包和存貯主機的設置數據,并把需要發送的數據包或設置完成數據包放在需要發送的數據緩沖區,接著改變下此時的狀態:為我組好了,準備發送數據了,接著觸發中斷,可以直接往串口發個數據即可,正常發送后,單片機會執行其他程序,等上位機接受到這個觸發數據后,下位機會中斷,中斷程序會根據狀態,一位位的發生緩沖區的數據,直到所有的數據發送完成,發送完成后還要置位到接受數據狀態0。
我的環境是atmega128
初始化
uchar LED_Temp=0xFF;
uchar OUT_temp=0x04;
static uchar Uart_Status;
static uchar R_Data_Lenth;
uchar Tx_Buf[TxBufSize];
uchar Rx_Buf[RxBufSize];
uchar *P_Uart_Rx;
uchar *P_Uart_Tx;
uchar Rx_Count;
uchar Tx_Count;
void Uart_Init(void)
{
//UCSR0B = 0x00; //先關閉
UCSR0A=0x00;
UCSR0C=0x06; //8 DATA ,1 STOP, NO PARITY
UCSR0B = (1< // RXCIE=1;TXCIE=1;UDREIE=0;RXEN=1;TXEN=1
Com_baudrate (9600);
P_Uart_Tx=Tx_Buf; //緩沖區指針定義
P_Uart_Rx=Rx_Buf;
Uart_Status=0; //開始時狀態為接受起始位狀態,其實這里是因為我在程序中用了通信協議
//本篇為基礎,就把協議的內容刪去了,僅僅提供了能運行的最簡單的框架
SEI(); //re-enable interrupts
}
//函數說明:波特率設置
void Com_baudrate (unsigned int baudrate)
{
unsigned int tmp;
tmp= 8000000/baudrate/16-1;
UBRR0H=(unsigned char)(tmp>>8);
UBRR0L=(unsigned char)tmp;
}
//函數說明:串口接收中斷函數
#pragma interrupt_handler uart0_rx_isr:iv_USART0_RXC
void uart0_rx_isr(void)
{
//這里填寫串口中斷處理的內容,可以添加協議,使用狀態機就可以了
//把接收到得內容放在緩沖區,然后再創建個處理緩沖區數據的函數,直接放在主循環中即可
}
//函數說明:串口發送完成中斷函數
#pragma interrupt_handler uart0_tx_isr:iv_USART0_TXC
void uart0_tx_isr(void)
{
//發送數據的處理函數
}
//函數說明:uart進程函數,放在大循環中
void Uart_Process(void)
{
//接收到得數據,再具體的在系統中實現,比如上位機的監控,或者傳輸數據等
}
//函數說明:uart測試程序
void Uart_Test(uchar data)
{
UDR0 = 0x01;//發送數據
}
//- 功能描述:串口發送字節的函數
//- 函數屬性:外部,使用戶使用
//- 參數說明:mydata:要發送的一個字節
//- 返回說明:無
//- 注:發送一個字節,是串口發送的基礎操作
void UART_Send_Byte(unsigned char mydata)
{
// UCSR0B = (1< UCSR0B &= ~((1< while(!(UCSR0A &(1< //等待發送緩沖區為空
UDR0 = mydata;
// delay_nms(5);
UCSR0B |= (1< //改的時候不要影響其它寄存器位,開串口中斷
}
評論