STM32串口寄存器操作(转)
生活随笔
收集整理的這篇文章主要介紹了
STM32串口寄存器操作(转)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
源:STM32串口寄存器操作
//USART.C/*********************************************************************************************************/ /* USART 收發 */ /* 陳鵬 20110611*/#include "SYSTEM.H" #include "GPIO_INIT.H" #include "USART.H"//定義串口通道號最大值 #define UART_ChMax 1//UART外設結構指針 static const USART_TypeDef * USARTxN[5] = {USART1,USART2,USART3,UART4,UART5};//相關UART狀態結構 typedef struct {FlagStatus NewDataFlag;//接收到新數據FlagStatus BuffFull; //接收Buff滿FlagStatus IntRx; //是否開啟中斷接收u8 *RxBuff;//接收Buff指針u16 RxBuffSize;//接收緩沖區大小,一幀數據大小u16 UartRxCnt;//接收數據計數器} UartRx_TypeDef;//UART1 接收狀態結構 static UartRx_TypeDef UartRx[UART_ChMax + 1];// //加入以下代碼,支持printf函數,而不需要選擇use MicroLIB #if 1 #pragma import(__use_no_semihosting) //標準庫需要的支持函數 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()以避免使用半主機模式 _sys_exit(int x) { x = x; } //重定義fputc函數 int fputc(int ch, FILE *f) { UARTx_SendByte(0,(u8)ch); return ch; } #endif
//end // /************************************************************************************************************************** 函數 : u8 UARTx_Init(u8 ch,u8 SYS_CLK,u32 Speed,u8 RX_Int)* 功能 : 串口初始化* 參數 : ch:通道選擇,0->usart1;SYS_CLK當前系統時鐘,Speed:串口速度,RX_Int:是否時能中斷接受* 返回 : 0:成功,1:失敗* 依賴 : 底層宏定義* 作者 : 陳鵬* 時間 : 20120403* 最后修改時間 : 20120403* 說明 : USART1~UART5,對應通道0~4 *************************************************************************************************************************/ u8 UARTx_Init(u8 ch,u8 SYS_CLK,u32 Speed,u8 RX_Int) {USART_TypeDef *UARTx = (USART_TypeDef *)USARTxN[ch]; //獲取對應通道硬件基址指針 u32 clock;u8 irq_n; float fclk; if(ch > UART_ChMax) return 1; //端口號超出范圍 //初始化UART IODeviceClockEnable(DEV_AFIO,ENABLE);//復用功能AFIO時鐘使能 switch (ch){ case 0: //通道0,USART1 ,TX:PA9;RX:PA10 {DeviceClockEnable(DEV_GPIOA,ENABLE);//GPIO A 時鐘使能DeviceClockEnable(DEV_USART1,ENABLE);//USART 1 時鐘使能 GPIOx_Init(GPIOA,BIT9,AF_PP, SPEED_10M); //PA09,TXD只能設置成復用推挽輸出GPIOx_Init(GPIOA,BIT10,IN_FLOATING,IN_IN); //浮空輸入DeviceReset(DEV_USART1);//復位串口1irq_n = IRQ_USART1;//串口1中斷號}break;
case 1: //通道1,USART2 ,TX:PA2;RX:PA3 { DeviceClockEnable(DEV_GPIOA,ENABLE);//GPIO A 時鐘使能DeviceClockEnable(DEV_USART2,ENABLE);//USART 2 時鐘使能 GPIOx_Init(GPIOA,BIT2,AF_PP, SPEED_10M); //PA2,TXD只能設置成復用推挽輸出GPIOx_Init(GPIOA,BIT3,IN_FLOATING,IN_IN); //浮空輸入DeviceReset(DEV_USART2);//復位串口2irq_n = IRQ_USART2;//串口2中斷號}break;
case 2: //通道2,USART3 ,TX:PD8;RX:PD9 {DeviceClockEnable(DEV_GPIOD,ENABLE);//GPIO D 時鐘使能DeviceClockEnable(DEV_USART3,ENABLE);//USART 3 時鐘使能 GPIOx_Init(GPIOD,BIT8,AF_PP, SPEED_10M); //PD8,TXD只能設置成復用推挽輸出GPIOx_Init(GPIOD,BIT9,IN_FLOATING,IN_IN); //浮空輸入DeviceReset(DEV_USART3);//復位串口3irq_n = IRQ_USART3;//串口3中斷號}break;
case 3: //通道3,UART4 ,TX:PC10;RX:PC11 {DeviceClockEnable(DEV_GPIOC,ENABLE);//GPIO C 時鐘使能DeviceClockEnable(DEV_UART4,ENABLE);//UART 4 時鐘使能GPIOx_Init(GPIOC,BIT10,AF_PP, SPEED_10M); //PC10,TXD只能設置成復用推挽輸出GPIOx_Init(GPIOD,BIT11,IN_FLOATING,IN_IN); //浮空輸入DeviceReset(DEV_UART4);//復位串口3irq_n = IRQ_UART4;//串口3中斷號}break;
case 4: //通道4,UART5 ,TX:PC12;RX:PD2 {DeviceClockEnable(DEV_GPIOC,ENABLE);//GPIO C 時鐘使能DeviceClockEnable(DEV_GPIOD,ENABLE);//GPIO D 時鐘使能DeviceClockEnable(DEV_UART5,ENABLE);//UART 5 時鐘使能GPIOx_Init(GPIOC,BIT12,AF_PP, SPEED_10M); //PC12,TXD只能設置成復用推挽輸出GPIOx_Init(GPIOD,BIT2,IN_FLOATING,IN_IN); //浮空輸入DeviceReset(DEV_UART5);//復位串口3irq_n = IRQ_UART5;//串口3中斷號}break;
default :
return 1;//端口號超出范圍,返回錯誤 }
//設置波特率分頻系數clock = SYS_CLK * 1000000;//USART1時鐘 if(ch > 0)clock /= 2; //USART2,3,4,5時鐘fclk = (float)clock / 16.0 / Speed;//計算波特率分頻系數clock = (u16)fclk;//得到波特率分頻系數整數部分 UARTx->BRR = clock << 4;//設置波特率整數部分fclk -= clock;//得到波特率分頻系數小數部分fclk *= 16;UARTx->BRR |= 0xf & (u16)fclk;//設置波特率小數部分 //配置UARTUARTx->CR1 = 0x2000;//使能USART,1個開始位,8位數據UARTx->CR1 |= 0x8;//置TE = 1;發送使能;發送第一個空閑位UARTx->CR1 |= 0x04;//RE = 1;接收使能SetUartRxBuff(ch,0,NULL);//設置串口接收緩沖區UARTx_ClearRxInt(ch); //清除串口接收中斷標志 if(RX_Int){UARTx->CR1 |= 0x20;//RXNEIE = 1,開RXNE中斷,即開啟接收中斷NVIC_IntEnable(irq_n,1);//開啟USART1全局中斷UartRx[ch].IntRx = SET;//中斷接收標志有效 } else{NVIC_IntEnable(irq_n,0); //關閉USART全局中斷UartRx[ch].IntRx = RESET;//中斷接收標志無效 }UARTx_SendByte(0,'S');//發送一字節數據 }/************************************************************************************************************************** 函數 : u8 UARTx_Config(u8 ch,UART_Config_TypeDef * cfg)* 功能 : 串口配置 * 參數 : ch:通道選擇,0->usart1;cfg:串口配置結構指針 * 返回 : 0:成功,非0:失敗 * 依賴 : 底層宏定義 * 作者 : 陳鵬 * 時間 : 20120408* 最后修改時間 : 20120408* 說明 : USART1~UART5,對應通道0~4 ,返回1:校驗設置錯誤,2:停止位設置錯誤,3:通道超出范圍 *************************************************************************************************************************/ u8 UARTx_Config(u8 ch,UART_Config_TypeDef * cfg){ USART_TypeDef *UARTx = (USART_TypeDef *)USARTxN[ch]; //獲取對應通道硬件基址指針if(ch > UART_ChMax)//判斷端口是否超出范圍 return 3; UARTx_PowerDown(ch);//進入掉電模式,進行配置 switch (cfg->OddEvenVerify)//設置校驗位 { case UART_VERIFY_NULL://無校驗 { UARTx->CR1 &= ~BIT12;//一個起始位,8個數據位 UARTx->CR1 &= ~BIT10;//禁止校驗控制 }break; case UART_ODD://奇校驗 { UARTx->CR1 |= BIT12;//一個起始位,9個數據位 UARTx->CR1 |= BIT10;//使能校驗控制 UARTx->CR1 |= BIT9;//奇校驗 }break; case UART_EVEN://偶校驗 { UARTx->CR1 |= BIT12;//一個起始位,9個數據位 UARTx->CR1 |= BIT10;//使能校驗控制 UARTx->CR1 &= ~BIT9;//偶校驗 }break; default : { UARTx_PowerOn(ch);//串口重新上電 return 1; //設置錯誤,返回校驗設置錯誤1 } } if(cfg->StopBitWidth == UART_STOP_1BIT) //設置停止位 { UARTx->CR2 &= ~(0x3 << 12);//清除設置,默認一個停止位 } else if(cfg->StopBitWidth == UART_STOP_2BIT) { UARTx->CR2 &= ~(0x3 << 12); UARTx->CR2 |= (0x2 << 12);//2個停止位 } else { UARTx_PowerOn(ch);//串口重新上電 return 2; //停止位設置錯誤,返回錯誤2 } UARTx_PowerOn(ch);//串口重新上電return 0; //設置完成,返回0 }/************************************************************************************************************************** 函數 : void UARTx_SendByte(u8 ch,u8 data)* 功能 : UART單字節發送 * 參數 : ch:通道號,dataL:要發送的數據 * 返回 : 無 * 依賴 : 底層宏定義 * 作者 : 陳鵬 * 時間 : 20120403* 最后修改時間 : 20120403* 說明 : 通道號為0 - 4;*************************************************************************************************************************/void UARTx_SendByte(u8 ch,u8 data){ USART_TypeDef *UARTx = (USART_TypeDef *)USARTxN[ch]; //獲取對應通道硬件基址指針if(ch > UART_ChMax)//判斷端口是否超出范圍 return;while(!(UARTx->SR & 0x80));//等待發送寄存器為空,(否則連續發送時數據易丟失 )UARTx->DR = data;//發送數據 while(!(UARTx->SR & 0x40));//等待TC = 1;也就是發送完成 UARTx->SR &= ~(1 << 6);//清除發送完成標志 }/************************************************************************************************************************** 函數 : void UARTx_TX(u8 ch,u8 *tx_buff,u16 byte_number)* 功能 : UART數據發送函數 * 參數 : ch:通道號,tx_buff:發送緩沖區,byte_number:需要發送的字節 * 返回 : 無 * 依賴 : void UART_SendByte(u8 ch,u8 data)* 作者 : 陳鵬 * 時間 : 20120403* 最后修改時間 : 20120403* 說明 : 非DMA方式,非FIFO方式發送 *************************************************************************************************************************/ void UARTx_TX(u8 ch,u8 *tx_buff,u16 byte_number){ u8 i;if(ch > UART_ChMax)//判斷端口是否超出范圍 return; for(i = 0;i < byte_number;i++)//循環發送,直至發送完畢 { UARTx_SendByte(ch,tx_buff[i]); }}/************************************************************************************************************************** 函數 : void UARTx_PowerDown(u8 ch)* 功能 : UART掉電 * 參數 : ch:通道選擇 * 返回 : 無 * 依賴 : 底層宏定義 * 作者 : 陳鵬 * 時間 : 20120403* 最后修改時間 : 20120403* 說明 : 進入低功耗模式;通道號為0 - 4;*************************************************************************************************************************/void UARTx_PowerDown(u8 ch){ if(ch > UART_ChMax)//判斷端口是否超出范圍 return; ((USART_TypeDef *)USARTxN[ch])->BRR |= (1 << 13);//UE位寫一,開啟低功耗 }/************************************************************************************************************************** 函數 : void UARTx_PowerOn(u8 ch)* 功能 : UART上電 * 參數 : ch:通道選擇 * 返回 : 無 * 依賴 : 底層宏定義 * 作者 : 陳鵬 * 時間 : 20120403* 最后修改時間 : 20120403* 說明 : 退出低功耗模式;通道號為0 - 4;*************************************************************************************************************************/void UARTx_PowerOn(u8 ch){ if(ch > UART_ChMax)//判斷端口是否超出范圍 return;((USART_TypeDef *)USARTxN[ch])->BRR &= ~(1 << 13);//UE位清零,退出低功耗模式 }/************************************************************************************************************************** 函數 : u8 GetUartNewFlag(u8 ch)* 功能 : 獲取串口新數據標志 * 參數 : ch:通道選擇 * 返回 : 1:有新數據,0:無新數據 * 依賴 : 底層宏定義 * 作者 : 陳鵬 * 時間 : 20120403* 最后修改時間 : 20120403* 說明 : 用于判斷是否有新的數據,會清除掉新數據標志的 *************************************************************************************************************************/ u8 GetUartNewFlag(u8 ch){ if(ch > UART_ChMax)//判斷端口是否超出范圍 return 0;if(UartRx[ch].IntRx == SET)//開啟了中斷接收 { if(UartRx[ch].NewDataFlag == SET) //有新數據 { UartRx[ch].NewDataFlag = RESET;//清除標志 return 1; //返回有新數據 } else return 0; //無新數據 } else //沒開啟中斷接收 { if(((USART_TypeDef *)USARTxN[ch])->SR & BIT5)//RXNE=1,接收到新數據 { ((USART_TypeDef *)USARTxN[ch])->SR &= ~BIT5;//清除標志 return 1; } else return 0; }}/************************************************************************************************************************** 函數 : u8 GetUartRxBuffFullFlag(u8 ch)* 功能 : 獲取串口接收緩沖區滿標志 * 參數 : ch:通道選擇 * 返回 : 1:有新數據,0:無新數據 * 依賴 : 底層宏定義 * 作者 : 陳鵬 * 時間 : 20120403* 最后修改時間 : 20120403* 說明 : 用于判斷接收緩沖區是否滿,會清除標志 *************************************************************************************************************************/ u8 GetUartRxBuffFullFlag(u8 ch){ if(ch > UART_ChMax)//判斷端口是否超出范圍 return 0; if(UartRx[0].BuffFull == SET)//緩沖區已滿 { UartRx[0].BuffFull = RESET;//清除滿標志 return 1; } return 0;}/************************************************************************************************************************** 函數 : void UART_ClearRxInt(u8 ch)* 功能 : 清除串口接收中斷標志 * 參數 : ch:通道選擇 * 返回 : 物 * 依賴 : 底層宏定義 * 作者 : 陳鵬 * 時間 : 20120403* 最后修改時間 : 20120403* 說明 : 用于清除接收標志 *************************************************************************************************************************/ void UARTx_ClearRxInt(u8 ch){ if(ch > UART_ChMax)//判斷端口是否超出范圍 return; ((USART_TypeDef *)USARTxN[ch])->SR &= ~BIT5;//清除標志
}/************************************************************************************************************************** 函數 : u8 GetUartNewData(u8 ch)* 功能 : 獲取串口新數據 * 參數 : ch:通道選擇 * 返回 : 收到的數據 * 依賴 : 底層宏定義 * 作者 : 陳鵬 * 時間 : 20120403* 最后修改時間 : 20120403* 說明 : 用于接收一個字節數據 *************************************************************************************************************************/ u8 GetUartNewData(u8 ch){ if(ch > UART_ChMax)//判斷端口是否超出范圍 return 0;return (((USART_TypeDef *)USARTxN[ch])->DR);//返回數據 }/************************************************************************************************************************** 函數 : void SetUartRxBuff(u8 ch,u16 RxBuffSize,u8 *RxBuff)* 功能 : 設置串口接收緩沖區 * 參數 : ch:通道選擇,RxBuffSize:緩沖區大小,RxBuff:緩沖區指針 * 返回 : 無 * 依賴 : 底層宏定義 * 作者 : 陳鵬 * 時間 : 20120403* 最后修改時間 : 20120403* 說明 : 一定要設置,否則開啟中斷接收時可能會異常 *************************************************************************************************************************/ void SetUartRxBuff(u8 ch,u16 RxBuffSize,u8 *RxBuff){ if(ch > UART_ChMax)//判斷端口是否超出范圍 return; UartRx[ch].RxBuffSize = RxBuffSize; //設置緩沖區大小 UartRx[ch].RxBuff = RxBuff;//設置緩沖區指針 UartRx[0].UartRxCnt = 0;//計數器清零 }/************************************************************************************************************************** 函數 : void USART1_IRQHandler (void)* 功能 : UART1中斷接收函數 * 參數 : 無 * 返回 : 無 * 依賴 : 底層宏定義 * 作者 : 陳鵬 * 時間 : 20110611* 最后修改時間 : 20120403* 說明 : 無 *************************************************************************************************************************/ void USART1_IRQHandler (void){ if((USART1->SR & BIT2) || (USART1->SR & BIT1))//如果NE = 1發送噪聲錯誤 //如果FE = 1,發送幀錯誤 { if(USART1->SR); if(USART1->DR);//復位NE操作序列 } else if(UartRx[0].RxBuffSize > 0)//接收緩沖區大于0 { (UartRx[0].RxBuff)[(UartRx[0].UartRxCnt) ++] = USART1->DR;//將數據存放到緩沖區 if(UartRx[0].UartRxCnt == UartRx[0].RxBuffSize)//緩沖區已滿 {UartRx[0].UartRxCnt = 0;//接收計數器清零UartRx[0].BuffFull = SET;//緩沖區已滿標志 } } UartRx[0].NewDataFlag = SET;//收到新數據標志 UARTx_ClearRxInt(0); //清除串口接收中斷標志 }#if UART_ChMax > 0/************************************************************************************************************************** 函數 : void USART2_IRQHandler (void)* 功能 : UART2中斷接收函數 * 參數 : 無 * 返回 : 無 * 依賴 : 底層宏定義 * 作者 : 陳鵬 * 時間 : 20110611* 最后修改時間 : 20120403* 說明 : 無 *************************************************************************************************************************/ void USART2_IRQHandler (void){ if((USART2->SR & BIT2) || (USART2->SR & BIT1))//如果NE = 1發送噪聲錯誤 //如果FE = 1,發送幀錯誤 { if(USART2->SR); if(USART2->DR);//復位NE操作序列 } else if(UartRx[1].RxBuffSize > 0)//接收緩沖區大于0 { (UartRx[1].RxBuff)[(UartRx[1].UartRxCnt) ++] = USART1->DR;//將數據存放到緩沖區 if(UartRx[1].UartRxCnt == UartRx[1].RxBuffSize)//緩沖區已滿 {UartRx[1].UartRxCnt = 0;//接收計數器清零UartRx[1].BuffFull = SET;//緩沖區已滿標志 } } UartRx[1].NewDataFlag = SET;//收到新數據標志 UARTx_ClearRxInt(1); //清除串口接收中斷標志 }#endif#if UART_ChMax > 1/************************************************************************************************************************** 函數 : void USART3_IRQHandler (void)* 功能 : UART3中斷接收函數 * 參數 : 無 * 返回 : 無 * 依賴 : 底層宏定義 * 作者 : 陳鵬 * 時間 : 20110611* 最后修改時間 : 20120403* 說明 : 無 *************************************************************************************************************************/ void USART3_IRQHandler (void){ if((USART3->SR & BIT2) || (USART3->SR & BIT1))//如果NE = 1發送噪聲錯誤 //如果FE = 1,發送幀錯誤 { if(USART3->SR); if(USART3->DR);//復位NE操作序列 } else if(UartRx[2].RxBuffSize > 0)//接收緩沖區大于0 { (UartRx[2].RxBuff)[(UartRx[2].UartRxCnt) ++] = USART1->DR;//將數據存放到緩沖區 if(UartRx[2].UartRxCnt == UartRx[2].RxBuffSize)//緩沖區已滿 {UartRx[2].UartRxCnt = 0;//接收計數器清零UartRx[2].BuffFull = SET;//緩沖區已滿標志 } } UartRx[2].NewDataFlag = SET;//收到新數據標志 UART_ClearRxInt(2); //清除串口接收中斷標志 }#endif#if UART_ChMax > 2/************************************************************************************************************************** 函數 : void UART4_IRQHandler (void)* 功能 : UART4中斷接收函數 * 參數 : 無 * 返回 : 無 * 依賴 : 底層宏定義 * 作者 : 陳鵬 * 時間 : 20110611* 最后修改時間 : 20120403* 說明 : 無 *************************************************************************************************************************/ void UART4_IRQHandler (void){ if((UART4->SR & BIT2) || (UART4->SR & BIT1))//如果NE = 1發送噪聲錯誤 //如果FE = 1,發送幀錯誤 { if(UART4->SR); if(UART4->DR);//復位NE操作序列 } else if(UartRx[3].RxBuffSize > 0)//接收緩沖區大于0 { (UartRx[3].RxBuff)[(UartRx[3].UartRxCnt) ++] = USART1->DR;//將數據存放到緩沖區 if(UartRx[3].UartRxCnt == UartRx[3].RxBuffSize)//緩沖區已滿 {UartRx[3].UartRxCnt = 0;//接收計數器清零UartRx[3].BuffFull = SET;//緩沖區已滿標志 } } UartRx[3].NewDataFlag = SET;//收到新數據標志 UART_ClearRxInt(3); //清除串口接收中斷標志 }#endif#if UART_ChMax > 3/************************************************************************************************************************** 函數 : void UART5_IRQHandler (void)* 功能 : UART5中斷接收函數 * 參數 : 無 * 返回 : 無 * 依賴 : 底層宏定義 * 作者 : 陳鵬 * 時間 : 20110611* 最后修改時間 : 20120403* 說明 : 無 *************************************************************************************************************************/ void UART5_IRQHandler (void){ if((UART5->SR & BIT2) || (UART5->SR & BIT1))//如果NE = 1發送噪聲錯誤 //如果FE = 1,發送幀錯誤 { if(UART5->SR); if(UART5->DR);//復位NE操作序列 } else if(UartRx[4].RxBuffSize > 0)//接收緩沖區大于0 { (UartRx[4].RxBuff)[(UartRx[4].UartRxCnt) ++] = USART1->DR;//將數據存放到緩沖區 if(UartRx[4].UartRxCnt == UartRx[4].RxBuffSize)//緩沖區已滿 {UartRx[4].UartRxCnt = 0;//接收計數器清零UartRx[4].BuffFull = SET;//緩沖區已滿標志 } } UartRx[4].NewDataFlag = SET;//收到新數據標志 UART_ClearRxInt(4); //清除串口接收中斷標志 }#endif#undef UART_ChMax //USART.H/**************************************************************************************************//* USART 通用同步異步串行發送接收*//* 陳鵬 20110609*/#ifndef _USART_H#define _USART_H#include "system.h"#include "stdio.h"//UART配置相關結構定義 typedef struct {u8 OddEvenVerify;//奇偶校驗,奇,偶,無u8 StopBitWidth;//停止位位寬1,2 } UART_Config_TypeDef;//奇偶校驗 #define UART_VERIFY_NULL 0//無校驗 #define UART_ODD 1//奇校驗 #define UART_EVEN 2//偶校驗 //停止位 #define UART_STOP_1BIT 0//一個停止位 #define UART_STOP_2BIT 1//2個停止位//相關API u8 UARTx_Init(u8 ch,u8 SYS_CLK,u32 Speed,u8 RX_Int);//串口初始化 u8 UARTx_Config(u8 ch,UART_Config_TypeDef * cfg); //串口配置 void UARTx_SendByte(u8 ch,u8 data); //UART單字節發送 void UARTx_TX(u8 ch,u8 *tx_buff,u16 byte_number); //UART數據發送函數 void UARTx_PowerDown(u8 ch); //UART掉電 void UARTx_PowerOn(u8 ch); //UART上電 u8 GetUartNewFlag(u8 ch); //獲取串口新數據標志 u8 GetUartRxBuffFullFlag(u8 ch); //獲取串口接收緩沖區滿標志 u8 GetUartNewData(u8 ch); //獲取串口新數據 void SetUartRxBuff(u8 ch,u16 RxBuffSize,u8 *RxBuff);//設置串口接收緩沖區 void UARTx_ClearRxInt(u8 ch); //清除串口接收中斷標志#endif
?
總結
以上是生活随笔為你收集整理的STM32串口寄存器操作(转)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 制作openstack-centos镜像
- 下一篇: 【转】GitHub入门详细讲解