usart即為通用同步非同步收發器,用於序列通訊,例如其可以用於列印程式輸出資訊,以便於除錯程式。
這裡簡單介紹下usart框圖。
tx為傳送資料的輸出引腳,rx為接收資料的輸入引腳,sclk為傳送器時鐘輸出引腳(同步模式下會用到)。其中sclk**於apb1匯流排時鐘(36mhz)和apb2匯流排時鐘(72mhz)。
這裡涉及到usart資料暫存器(usart_dr)。如圖10-2。
從圖10-2的暫存器描述我們知道,usart_dr實際上包含了乙個傳送用的tdr暫存器,乙個接收用的rdr暫存器。傳送時,把tdr內容轉移到傳送移位暫存器,由傳送移位暫存器一位一位發出;接收時,把收到的每一位儲存到接收移位暫存器然後再轉移到rdr。
usart有專門的傳送器和接收器,在使用usart前需要先使能usart,將usart_cr1暫存器的ue位置1即可。而傳送或接收的資料字長可選8位或9位,由usart_cr1的m位控制。
要啟動資料傳送,需要先使能usart_cr1的te位,則傳送移位暫存器的資料會在tx引腳輸出,從低位開始傳送,如果是同步模式,則sclk也會輸出時鐘訊號。在非同步模式中,乙個字元幀包含三部分:起始位+資料幀+停止位。中間部分的資料幀則是我們要傳送的8位或9位資料。當使能te位後,傳送器開始會先傳送乙個空閒幀,然後往usart_dr寫入要傳送的資料。傳送完成後,等待狀態暫存器(usart_sr)的tc位置1後,則代表資料傳輸完成,同時如果usart_cr1的tcie位置1,將產生中斷。
同理,在接收時,需要置位usart_cr1的re位,使能接收。接收完成後,會把usart_sr的rxne位置1,同時如果usart_cr1的rxneie位置1,可以產生中斷。
usart中,波特率和位元率的值相等,所以一般不區分這兩個概念。波特率越大,傳輸速率越快。usart的傳送器和接收器使用相同的波特率,公式如下:
boud =其中boud為波特率的值,f為usart時鐘頻率,usartdiv是usart分頻器除法因子,如圖10-3的暫存器描述。
由描述可知,div_mantissa為usartdiv的整數部分,div_fraction為usartdiv的小數部分。那麼,
usartdiv = div_mantissa + div_fraction / 16波特率的常用值有2400、9600、19200、115200。
例如,掛載在apb2匯流排的usart1,其有72mhz的時鐘頻率,即f=72mhz,假設我們需要115200的波特率,則由上面的公式可得:
115200 = 72000000 / (16*usartdiv)我們能得到usartdiv=39.0625,那麼
div_mantissa=39=0x17,這時我們應該設定usart_brr的值為0x171。div_fraction=0.625*16=1=0x01
usart還支援奇偶校驗。當使用校驗位時,資料幀長度為8位資料幀加上1位校驗位,共9位,此時usart_cr1的m位需要置1。將usart_cr1的pce位置1可以使能校驗控制。奇偶校驗由硬體自動完成,在傳送資料時會自動新增校驗位,接收資料時會自動驗證校驗位。接收資料驗證校驗位時如果校驗失敗,usart_sr的pe位將會置1,同時如果usart_cr1的peie位置1,便能產生奇偶校驗中斷。
使能校驗控制後,每個字元幀組成將變為:起始位+資料幀+校驗位+停止位。
我們在寫微控制器程式的時候,在debug時,往往要用到串列埠輸出資訊,這是會使用printf列印出我們想要的資訊來,但是printf有乙個弊端,就是輸出列印時間較長。這樣在一些對時間精度要求非常高的場合,使用printf將會帶來一系列問題,這時,如果使用微控制器的usart自定義乙個協議,直接傳送資料到上位機,將會得到我們想要的效果。下面對怎樣使用usart傳送資料做乙個整理。
void usart1_putchar(usart_typedef * usartx,u8 ch)
void usart1_putstrlen(usart_typedef * usartx,u8 *buf,u16 len)
while(usart_getflagstatus(usartx,usart_flag_tc) == reset);
}
void usart1_putstr(usart_typedef * usartx,u8 *buf)
while(usart_getflagstatus(usartx,usart_flag_tc) == reset);
// 這句話有必要加,他是用於檢查串列埠是否傳送完成的標誌,如果不加這句話會發生資料丟失的情況。
}
該函式就可以像printf使用可變引數。通過觀察函式但這個函式只支援了%d,%s的引數,想要支援更多,可以仿照printf的函式寫法加以補充。
void usart_printf ( usart_typedef * usartx, char * data, ... )
} else if ( * data == '%')
data++;
break;
case 'd'://十進位制
d = va_arg(ap, int);
itoa(d, buf, 10);
for (s = buf; *s; s++)
data++;
break;
default:
data++;
break;
}
} else
usart_senddata(usartx, *data++);
while ( usart_getflagstatus ( usartx, usart_flag_txe ) == reset );
}}
資料的頭標識為「\n」既換行符,尾標識為「+」。該函式將串列埠接收的資料存放在usart_buffer陣列中,然後先判斷當前字元是不是尾標識,如果是說明接收完畢,然後再來判斷頭標識是不是「+」號,如果還是那麼就是我們想要的資料,接下來就可以進行相應資料的處理了。但如果不是那麼就讓usart2_rx=0重新接收資料。這樣做的有以下好處:
這裡我的把接收正確資料直接列印出來,也可以通過設定標識位,然後在主函式裡面輪詢再操作。
void usart2_irqhandler()
else
} }}
串列埠空閒中斷,一幀資料過來中斷進入一次且接收的資料時候是dma來搬運到指定緩衝區(程式中是usart1_receive_dmabuffer陣列),不占用cpu時間。
#define dma_usart1_receive_len 18 //根據需要設定
void usart1_irqhandler(void)
//設定傳輸資料長度
dma_setcurrdatacounter(dma1_channel5,dma_usart1_receive_len);
//開啟dma
dma_cmd(dma1_channel5,enable);
}
}
STM32 USART傳送標誌 TXE TC
在usart的傳送端有2個暫存器,乙個是程式可以看到的usart dr暫存器,另乙個是程式看不到的移位暫存器,對應usart資料傳送有兩個標誌,乙個是txe 傳送資料暫存器空,另乙個是tc 傳送結束。當usart dr中的資料傳送到移位暫存器後,txe被設定,此時移位暫存器開始向tx訊號線按位傳輸資...
藍橋杯嵌入式 USART(按 n傳送)
一 基本資料 快速編寫 6 stm32韌體庫 v3.5版 stm32f10x stdperiph lib stm32f10x stdperiph lib v3.5.0 project stm32f10x stdperiph examples usart interrupt usart.c inclu...
usart串列埠使用
stm32串列埠使用 1 printf函式呼叫 iar的option設定中將printf庫開啟再編寫printf重定向到usartn的函式 int fputc int ch,file f return ch 使用usb轉ttl直接連線mcu與計算機即可。除ttl外,rs232與rs485都可作為串列...