STM32學(xué)習(xí)筆記USART程序解釋原子_第1頁
STM32學(xué)習(xí)筆記USART程序解釋原子_第2頁
STM32學(xué)習(xí)筆記USART程序解釋原子_第3頁
STM32學(xué)習(xí)筆記USART程序解釋原子_第4頁
STM32學(xué)習(xí)筆記USART程序解釋原子_第5頁
已閱讀5頁,還剩2頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

1、USART程序分析一 .H文件#ifndef _USART_H#define _USART_H#include <stm32f10x_lib.h>#include "stdio.h"extern u8 USART_RX_BUF64; /接收緩沖,最大63個字節(jié).末字節(jié)為換行符 extern u8 USART_RX_STA; /接收狀態(tài)標(biāo)記/如果想串口中斷接收,請不要注釋以下宏定義/#define EN_USART1_RX 使能串口1接收void uart_init(u32 pclk2,u32 bound);#endif 解釋:extern 作用域:如果整個工程由

2、多個文件組成,在一個文件中想引用另外一個文件中已經(jīng)定義的外部變量時,則只需在引用變量的文件中用extern關(guān)鍵字加以聲明即可。可見,其作用域從一個文件擴(kuò)展到多個文件了。例子:文件a.c的內(nèi)容:#include <stdio.h>int BASE=2;/變量定義int exe(int x); /外部函數(shù)提前聲明int main(int argc, char *agrv) int a=10; printf("%d%d = %dn",BASE,a,exe(a); return 0;文件b.c的內(nèi)容:#include <stdio.h>extern BASE

3、;/外部變量聲明int exe(int x) int i; int ret=1; for(i=0;i<x;i+) ret*=BASE; return ret;利用gcc工具編譯gcc a.c b.c o demo,再運行./demo,結(jié)果為210 = 1024。其中,在a.c文件中定義BASE=2,在b.c中引用BASE時,需要用extern關(guān)鍵字聲明其為外部變量,否則編譯會找不到該變量。 二 .C文件#include "sys.h"#include "usart.h"/加入以下代碼,支持printf函數(shù),而不需要選擇use MicroLIB #i

4、f 1#pragma import(_use_no_semihosting) /標(biāo)準(zhǔn)庫需要的支持函數(shù) struct _FILE int handle; /* Whatever you require here. If the only file you are using is */ /* standard output using printf() for debugging, no file handling */ /* is required. */ ; /* FILE is typedef d in stdio.h. */ FILE _stdout; /定義_sys_exit()以避免

5、使用半主機(jī)模式 _sys_exit(int x) x = x; 解釋:一些支持的函數(shù)。/重定義fputc函數(shù) int fputc(int ch, FILE *f) while(USART1->SR&0X40)=0);/循環(huán)發(fā)送,直到發(fā)送完畢 USART1->DR = (u8) ch; return ch;#endif解釋:最后這里就是定義printf的輸出執(zhí)行單元了,比如現(xiàn)在是串口1輸出,如果你要串口2,那么設(shè)置USART1為USART2即可。#ifdef EN_USART1_RX /如果使能了接收/串口1中斷服務(wù)程序/注意,讀取USARTx->SR能避免莫名其妙的錯

6、誤 u8 USART_RX_BUF64; /接收緩沖,最大64個字節(jié)./接收狀態(tài)/bit7,接收完成標(biāo)志/bit6,接收到0x0d/bit50,接收到的有效字節(jié)數(shù)目u8 USART_RX_STA=0; /接收狀態(tài)標(biāo)記 void USART1_IRQHandler(void)u8 res; if(USART1->SR&(1<<5)/接收到數(shù)據(jù) res=USART1->DR; if(USART_RX_STA&0x80)=0)/接收未完成if(USART_RX_STA&0x40)/接收到了0x0dif(res!=0x0a)USART_RX_STA=0;

7、/接收錯誤,重新開始else USART_RX_STA|=0x80;/接收完成了 else /還沒收到0X0Dif(res=0x0d)USART_RX_STA|=0x40;elseUSART_RX_BUFUSART_RX_STA&0X3F=res;USART_RX_STA+;if(USART_RX_STA>63)USART_RX_STA=0;/接收數(shù)據(jù)錯誤,重新開始接收 #endif解釋:void USART1_IRQHandler(void)函數(shù)是一個串口1 中斷響應(yīng)函數(shù),當(dāng)串口1 發(fā)生了相應(yīng)的中斷后,就會跳到該函數(shù)執(zhí)行。這里我們設(shè)計了一個小小的接收協(xié)議:通過這個函數(shù),配合一個

8、數(shù)組USART_RX_BUF64,一個接收狀態(tài)寄存器USART_RX_STA 實現(xiàn)對串口數(shù)據(jù)的接收管理。USART_RX_BUF 的最大值為64,也就是一次接收的數(shù)據(jù)最大不能超過64 個字節(jié)。USART_RX_STA 是一個接收狀態(tài)寄存器其各的定義如下表:設(shè)計思路如下:當(dāng)接收到從電腦發(fā)過來的數(shù)據(jù),把接收到的數(shù)據(jù)保存在USART_RX_BUF 中,同時在接收狀態(tài)寄存器(USART_RX_STA)中計數(shù)接收到的有效數(shù)據(jù)個數(shù),當(dāng)收到回車(0X0D,0X0A)的第一個字節(jié)0X0D 時,計數(shù)器將不再增加,等待0X0A 的到來,而如果0X0A 沒有來到,則認(rèn)為這次接收失敗,重新開始下一次接收。如果順利接收

9、到0X0A,則標(biāo)記USART_RX_STA的第七位,這樣完成一次接收,并等待該位被其他程序清除,從而開始下一次的接收,而如果遲遲沒有收到0X0D,那么在接收數(shù)據(jù)超過64 個了,則會丟棄前面的數(shù)據(jù),重新接收。USART1->SR的第5位:USART1->DR通過上述分析,程序便可以理解。/初始化IO 串口1/pclk2:PCLK2時鐘頻率(Mhz)/bound:波特率/CHECK OK/091209void uart_init(u32 pclk2,u32 bound) float temp;u16 mantissa;u16 fraction; temp=(float)(pclk2*1

10、000000)/(bound*16);/得到USARTDIVmantissa=temp; /得到整數(shù)部分fraction=(temp-mantissa)*16; /得到小數(shù)部分 mantissa<<=4;mantissa+=fraction; RCC->APB2ENR|=1<<2; /使能PORTA口時鐘 RCC->APB2ENR|=1<<14; /使能串口時鐘 GPIOA->CRH&=0XFFFFF00F; GPIOA->CRH|=0X000008B0;/IO狀態(tài)設(shè)置 RCC->APB2RSTR|=1<<1

11、4; /復(fù)位串口1RCC->APB2RSTR&=(1<<14);/停止復(fù)位 /波特率設(shè)置 USART1->BRR=mantissa; / 波特率設(shè)置 USART1->CR1|=0X200C; /1位停止,無校驗位.#ifdef EN_USART1_RX /如果使能了接收/使能接收中斷USART1->CR1|=1<<8; /PE中斷使能USART1->CR1|=1<<5; /接收緩沖區(qū)非空中斷使能 MY_NVIC_Init(2,3,USART1_IRQChannel,2);/組2,最低優(yōu)先級 #endif解釋:STM32的

12、每個串口都有一個自己獨立的波特率寄存器USART_BRR,通過設(shè)置該寄存器就可以達(dá)到配置不同波特率的目的。其各位描述如下圖所示:前面提到STM32的分?jǐn)?shù)波特率概念,其實就是在這個寄存器(USART_BRR)里面體現(xiàn)的。USART_BRR的最低4位(位3:0)用來存放小數(shù)部分DIV_Fraction,緊接著的12位(位15:4)用來存放整數(shù)部分DIV_Mantissa,最高16位未使用。這里,我們簡單介紹一下波特率的計算,STM32的串口波特率計算公式如下:上式中,是給串口的時鐘(PCLK1用于USART2、3、4、5,PCLK2用于USART1);USARTDIV是一個無符號定點數(shù)。我們只要得

13、到USARTDIV的值,就可以得到串口波特率寄存器USART1->BRR的值,反過來,我們得到USART1->BRR的值,也可以推導(dǎo)出USARTDIV的值。但我們更關(guān)心的是如何從USARTDIV的值得到USART_BRR的值,因為一般我們知道的是波特率,和PCLKx的時鐘,要求的就是USART_BRR的值。下面我們來介紹如何通過USARTDIV得到串口USART_BRR寄存器的值。假設(shè)我們的串口1要設(shè)置為9600的波特率,而PCLK2的時鐘為72M。這樣,我們根據(jù)上面的公式有:USARTDIV=72000000/(9600*16)=468.75那么得到:DIV_Fraction=1

14、6*0.75=12=0X0C;DIV_Mantissa= 468=0X1D4;這樣,我們就得到了USART1->BRR的值為0X1D4C。只要設(shè)置串口1的BRR寄存器值為0X1D4C就可以得到9600的波特率。當(dāng)然,并不是任何條件下都可以隨便設(shè)置串口波特率的,在某些波特率和PCLK2頻率下,還是會存在誤差的,具體可以參考STM32參考手冊的第525頁的表176。接下來,我們就可以初始化串口了,需要注意的是這里初始化串口是按8位數(shù)據(jù)格式,1位停止位,無奇偶校驗位的。RCC->APB2ENR|=1<<14; /使能串口時鐘寄存器位如下:位14 USART1EN:USART1時鐘使能 由軟件置1或清0 0:USART1時鐘關(guān)閉; 1:USART1時鐘開啟。 GPIOA->CRH&=0XFFFFF00F; GPIOA->CRH|=0X000008B0;/IO狀態(tài)設(shè)置IO設(shè)置成上啦或下拉模式,一個輸入一個輸出。RCC->APB2RSTR|=1<<14; /復(fù)位串口1RCC->APB2RSTR&=(1<<14);/停止復(fù)位具體查看RCC->APB2RSTR寄存器的定義。USART1->CR1|=0X200C; /1位停止,無校驗位.USART1

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論