CW32L083的UART是沒有空閑中斷的,這樣給接收數據幀帶來一定的不便。比如我們需要用的AT指令,那么判斷接收完一條完整的指令,可以用串口斷+結尾rn來判斷接收完一條完整指令。但是這個方法有一個缺點就是返回兩個rn 時就會處理起來非常麻煩。
這是我用串口中斷+定時器來實現 如空閑中斷的接收,而且可以靈活的處理接收最后一個數據后的延時來判是否接收完整一條指令。
【實現方法】
1、初始化串口5,開配置波特率為115200,開啟接收中斷。
static void SerialInit(uint32_t BaudRate)
{
uint32_t PCLK_Freq;
GPIO_InitTypeDef GPIO_InitStructure = {0};
UART_InitTypeDef UART_InitStructure = {0};
PCLK_Freq = SystemCoreClock > > pow2_table[CW_SYSCTRL- >CR0_f.HCLKPRS];
PCLK_Freq > >= pow2_table[CW_SYSCTRL- >CR0_f.PCLKPRS];
// 調試串口使用UART5
// PB8- >TX
// PB9< -RX
// 時鐘使能
__RCC_GPIOB_CLK_ENABLE();
__RCC_UART5_CLK_ENABLE();
// 先設置UART TX RX 復用,后設置GPIO的屬性,避免口線上出現毛刺
PB08_AFx_UART5TXD();
PB09_AFx_UART5RXD();
GPIO_InitStructure.Pins = GPIO_PIN_8;
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_Init(CW_GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.Pins = GPIO_PIN_9;
GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
GPIO_Init(CW_GPIOB, &GPIO_InitStructure);
UART_InitStructure.UART_BaudRate = BaudRate;
UART_InitStructure.UART_Over = UART_Over_16;
UART_InitStructure.UART_Source = UART_Source_PCLK;
UART_InitStructure.UART_UclkFreq = PCLK_Freq;
UART_InitStructure.UART_StartBit = UART_StartBit_FE;
UART_InitStructure.UART_StopBits = UART_StopBits_1;
UART_InitStructure.UART_Parity = UART_Parity_No;
UART_InitStructure.UART_HardwareFlowControl = UART_HardwareFlowControl_None;
UART_InitStructure.UART_Mode = UART_Mode_Rx | UART_Mode_Tx;
UART_Init(CW_UART5, &UART_InitStructure);
//優先級,無優先級分組
NVIC_SetPriority(UART2_UART5_IRQn, 0);
//UARTx中斷使能
NVIC_EnableIRQ(UART2_UART5_IRQn);
}
2、定義一個結構體來儲存串口的數據:
typedef struct _uartx_infor{
uint8_t rx_cnt;
uint8_t tx_cnt;
uint8_t rx_buff[UART_LEN_MAX];
uint8_t tx_buff[UART_LEN_MAX];
FunctionalState rx_state; //接收狀態
} uartx_infor;
3、初始化GTIM1定時器,定義為一次計時,主頻為64M,所以配置16分頻 預載值為40000,從而實現10毫秒溢出產生中斷。
/* 初始化GTIM定時1 創建10ms的中斷*/
void init_gtim1(void)
{
GTIM_InitTypeDef GTIM_InitStruct = {0};
__RCC_GTIM1_CLK_ENABLE(); // GTIM1時鐘使能
__disable_irq();
NVIC_EnableIRQ(GTIM1_IRQn);
__enable_irq();
GTIM_InitStruct.Mode = GTIM_MODE_TIME;
GTIM_InitStruct.OneShotMode = GTIM_COUNT_ONESHOT; //只運行一次
GTIM_InitStruct.Prescaler = GTIM_PRESCALER_DIV16;
GTIM_InitStruct.ReloadValue = 40000UL - 1; // PWM頻率為 64M/16/ 4M =100Hz
GTIM_InitStruct.ToggleOutState = DISABLE;
GTIM_TimeBaseInit(CW_GTIM1, >IM_InitStruct);
GTIM_ITConfig(CW_GTIM1, GTIM_IT_OV, ENABLE);
//GTIM_Cmd(CW_GTIM1, ENABLE);
}
4、定義串口中斷函數如下,主要的思想就是觸發接收中斷后,停止定時器的運行,重裝ARR值,再開啟定時器,同時把接收到的數據放入緩沖區。如果接收大于最大緩沖區,則接收值歸零。
/**
* @brief This funcation handles UART2
*/
void UART2_UART5_IRQHandler(void)
{
/* USER CODE BEGIN */
uint8_t rx_data;
if(UART_GetITStatus(CW_UART5, UART_IT_RC) != RESET)
{
uart5_infor.rx_state = DISABLE;
rx_data = UART_ReceiveData_8bit(CW_UART5);
if(uart5_infor.rx_cnt < UART_LEN_MAX)
{
uart5_infor.rx_buff[uart5_infor.rx_cnt] = rx_data;
CW_GTIM1- >CR0_f.EN = 0;
CW_GTIM1- >ARR = 40000-1;
CW_GTIM1- >CR0_f.EN = 1;
}
else
{
uart5_infor.rx_cnt = 0;
memset(uart5_infor.rx_buff, 0, UART_LEN_MAX);
}
uart5_infor.rx_cnt ++;
UART_ClearITPendingBit(CW_UART5, UART_IT_RC);
}
/* USER CODE END */
}
5、定時器函數為,如果觸發中斷,清除中斷標志,把接收完整數據值置為真:
/**
* @brief This funcation handles GTIM1
*/
void GTIM1_IRQHandler(void)
{
/* USER CODE BEGIN */
if(GTIM_GetITStatus(CW_GTIM1, GTIM_IT_OV))
{
GTIM_ClearITPendingBit(CW_GTIM1, GTIM_IT_OV);
uart5_infor.rx_state = ENABLE;
}
/* USER CODE END */
}
6、在主函數中,我們判斷接收狀態是否為真,如果為真則打印出接收的數值,并且重置串口數據。
while (1)
{
if(uart5_infor.rx_state == ENABLE)
{
printf("uart5 recv cnt:%drn", uart5_infor.rx_cnt);
printf("uart5 recv cnt:%srn", uart5_infor.rx_buff);
uart5_infor_init();
}
// GPIO_TogglePin(CW_GPIOC, GPIO_PIN_2);
// rt_thread_mdelay(500);
rt_thread_mdelay(10);
}
【實驗效果】
我們發送不定長數據,正確的從串口返回數據:


【總結】
用定時器與串口中斷結合起來,完美的實現了串口的不定長接收。
審核編輯:湯梓紅
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。
舉報投訴
-
指令
+關注
關注
1文章
623瀏覽量
37529 -
中斷
+關注
關注
5文章
917瀏覽量
43754 -
定時器
+關注
關注
23文章
3368瀏覽量
123575 -
串口
+關注
關注
15文章
1618瀏覽量
82803 -
uart
+關注
關注
22文章
1314瀏覽量
106634
發布評論請先 登錄
相關推薦
熱點推薦
CW32定時器及中斷介紹
可以由硬件自 動執行觸發信號的濾波操作,還能令觸發事件產生中斷和 DMA 請求。
低功耗定時器:CW32L083 內部集成 1 個 16 位低功耗定時器(LPTIM),可以以很低的
發表于 12-01 07:08
CW32L083的基本定時器
CW32L083 內部集成 3 個基本定時器 (BTIM),每個 BTIM 完全獨立且功能完全相同,各包含一個 16bit 自動重裝 載計數器并由一個可編程預分頻器驅動。BTIM 支持
發表于 12-15 06:23
CW32L083產品介紹
CW32L083是一款基于eFlash的單芯片低功耗微控制器,集成了ARM?Cortex?-M0+
核心,主頻高達64MHz,高速嵌入式存儲器(高達256K字節的FLASH和
高達24K字節
發表于 09-14 06:41
CW32L083微控制器數據手冊
定時器以及一組高級控制 PWM 定時器。CW32L083 可以在 -40° C 到 85° C 的溫度范圍內工作,供電電壓寬達 1.65V ~ 5.5V。支持 Sleep 和 DeepSleep兩種低功耗工作模式。
發表于 09-14 06:27
STM32之串口DMA接收不定長數據
使用stm32或者其他單片機的時候,會經常使用到串口通訊,那么如何有效地接收數據呢?假如這段數據是不定長的有如何高效
發表于 12-24 19:03
?30次下載
CW32L083串口中斷+定時器實現不定長數據接收
評論