1. 程式人生 > >stm32-串口

stm32-串口

錯誤 最大 長度 blog 中斷函數 rate 串口數據 font uart

USART:(Universal Synchronous/Asynchronous Receiver/Transmitter) 通用同步/異步串行接收/發送器 USART是一個全雙工通用同步/異步串行收發模塊,該接口是一個高度靈活的串行通信設備。

串口設置的一般步驟可以總結為如下幾個步驟:

1) 串口時鐘使能,GPIO 時鐘使能

2) 串口復位

3) GPIO 端口模式設置

4) 串口參數初始化

5) 開啟中斷並且初始化 NVIC(如果需要開啟中斷才需要這個步驟)NVIC :提供中斷控制器,用於總體管理異常,稱之為“嵌套向量中斷控制器:Nested Vectored Interrupt Controller (NVIC)”。NVIC和處理器內核緊密相連.具體看這個點擊打開鏈接

6) 使能串口

7) 編寫中斷處理函數

接下來我們按照以上步驟來編寫串口初始化函數

#include "stm32f10x.h"
#include "usart.h"


#if EN_USART1_RX //如果使能了接收
//串口1中斷服務程序
//註意,讀取USARTx->SR能避免莫名其妙的錯誤
u8 USART_RX_BUF[USART_REC_LEN]; //接收緩沖,最大USART_REC_LEN個字節.
//接收狀態
//bit15, 接收完成標誌
//bit14, 接收到0x0d
//bit13~0, 接收到的有效字節數目
u16 USART_RX_STA=0; //接收狀態標記

void uart_init(u32 bound)//這裏有個疑問,為什麽命名是uart,a代表異步,為什麽是異步
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA,ENABLE);//要用到的外設時鐘使能,均在總線APB2上

GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;//由原理圖可得,這個端口發送數據
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//推挽輸出
GPIO_Init(GPIOA,&GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;//浮空輸入模式
GPIO_Init(GPIOA,&GPIO_InitStructure);//由原理圖得,這個端口接受串口數據


USART_InitStructure.USART_BaudRate=bound;//串口波特率
USART_InitStructure.USART_WordLength=USART_WordLength_8b;//字長為8位數據格式
USART_InitStructure.USART_StopBits=USART_StopBits_1;//一個停止位
USART_InitStructure.USART_Parity=USART_Parity_No;//parity奇偶性 無奇偶校驗位
USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;//關閉硬件流控制(用於防止數據因接受不及丟失)
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//收發模式

//Usart1 NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//搶占優先級3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;//子優先級3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//IRQ通道使能 中斷請求通? ?
NVIC_Init(&NVIC_InitStructure);//根據指定的參數初始化NVIC寄存器

USART_Init(USART1, &USART_InitStructure); //初始化串口1
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//開啟串口接受中斷
USART_Cmd(USART1, ENABLE); //使能串口1
}

這裏沒什麽特別要說的,註意irq 是interrupt request,如果不打開,接收數據的中斷請求信號就會發不出去,也就是說,單片機接收不到信息

再看中斷函數

void USART1_IRQHandler(void)//串口1中斷服務程序,中斷服務程序的名字在core文件夾的匯編文件中定義
{
u8 Res;
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中斷(接收到的數據必須是0x0d 0x0a結尾),RXNE接收數據寄存器非空標誌位
{
Res =USART_ReceiveData(USART1);//讀取接收到的數據

if((USART_RX_STA&0x8000)==0)//接收未完成
{
if(USART_RX_STA&0x4000)//接收到了0x0d
{
if(Res!=0x0a)USART_RX_STA=0;//接收錯誤,重新開始
else USART_RX_STA|=0x8000;//接收完成了
}
else //還沒收到0X0D
{
if(Res==0x0d)USART_RX_STA|=0x4000;
else
{
USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
USART_RX_STA++;
if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收數據錯誤,重新開始接收
}
}
}
}
}
#endif

這裏我一開始看不懂,發現前面原來有講,是我沒看。。。。

技術分享

主函數如下

#include "stm32f10x.h"
#include "usart.h"


void delayms(u16 a)
{
u16 i,j;
for(i=0;i<a;i++)
{
j=8000;
while(j--);
}
}
int main(void)
{
u8 t;
u8 len;
u16 times=0;

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 設置中斷優先級分組2
uart_init(9600);//串口初始化為9600


while(1)
{
if(USART_RX_STA&0x8000)
{
len=USART_RX_STA&0x3fff;//得到此次接收到的數據長度
for(t=0;t<len;t++)
{
USART1->DR=USART_RX_BUF[t];
while((USART1->SR&0X40)==0);//等待發送結束
}
USART_RX_STA=0;
delayms(10);
}
}
}

今後繼續補充

stm32-串口