<p><iframe name="ifd" src="https://mnifdv.cn/resource/cnblogs/LearnHC32F460" frameborder="0" scrolling="auto" width="100%" height="1500"></iframe></p>
說明
HC32F460基礎例程源碼下載鏈接: https://github.com/yangfengwu45/learnHC32F460.git
基礎外設例程是提供給已經開發過M0或M1或M3或M4等ARM內核單片機的開發人員!
例程精簡扼要, 力求讓開發人員快速使用華大單片機做項目!
這節說一下串口.
先提示一個事情
1.打開數據手冊
2.第33頁(我以自己使用的HC32F460JETA為例)
主要說一下后面的 Func_Grp
3.然后找到38頁
4.列如:PC0
PC0后面寫的是 Func_Grp1
那么這個引腳可以作為這些功能使用
5.單片機的USART ,SPI, I2C, I2S, 不是固定的引腳,自己根據表格去指定
6.華大給了好幾個串口的例子
基本使用
1.串口基本的初始化
usart.c
#define USART_C_ #include "usart.h" /******************************************************************************* ** \brief USART RX irq callback function.//串口接收中斷函數 ** \param [in] None ** \retval None ******************************************************************************/ static void Usart1RxIrqCallback(void) { uint16_t m_u16RxData; m_u16RxData = USART_RecData(M4_USART1);//獲取串口接收的數據 } /******************************************************************************* ** \brief USART RX error irq callback function.(串口接收錯誤中斷處理函數) ** \param [in] None ** \retval None ******************************************************************************/ static void Usart1ErrIrqCallback(void) { if (Set == USART_GetStatus(M4_USART1, UsartFrameErr)){ USART_ClearStatus(M4_USART1, UsartFrameErr);} else{} if (Set == USART_GetStatus(M4_USART1, UsartParityErr)) {USART_ClearStatus(M4_USART1, UsartParityErr);} else{} if (Set == USART_GetStatus(M4_USART1, UsartOverrunErr)) {USART_ClearStatus(M4_USART1, UsartOverrunErr);} else{} } /******************************************************************************* ** \brief 串口初始化 ** \param [in] None ** \retval None ******************************************************************************/ void usart_init(void) { en_result_t enRet = Ok; stc_irq_regi_conf_t stcIrqRegiCfg; /*配置串口使用的時鍾和基本通信配置*/ const stc_usart_uart_init_t stcInitCfg = { UsartIntClkCkNoOutput, //使用內部時鍾源,不需要在其時鍾輸出IO上輸出通信的時鍾信號 UsartClkDiv_1, //時鍾不分頻 UsartDataBits8, //一個字節數據用8位數據位表示 UsartDataLsbFirst, //先傳輸低位 UsartOneStopBit, //停止位1位 UsartParityNone, //無奇偶校驗 UsartSamleBit8, //每次傳輸8位(1字節),也可以傳輸 UsartSamleBit16(16位,2字節) UsartStartBitFallEdge, UsartRtsEnable, //使能RTS (串口開始傳輸前讓RTS輸出一個高脈沖信號) }; /* Enable peripheral clock *//*打開時鍾*/ PWC_Fcg1PeriphClockCmd(PWC_FCG1_PERIPH_USART1 | PWC_FCG1_PERIPH_USART2 | \ PWC_FCG1_PERIPH_USART3 | PWC_FCG1_PERIPH_USART4, Enable); /* Initialize USART IO */ /*配置相應的IO作為串口的TX,RX引腳*/ PORT_SetFunc(USART1_RX_PORT, USART1_RX_PIN, Func_Usart1_Rx, Disable); PORT_SetFunc(USART1_TX_PORT, USART1_TX_PIN, Func_Usart1_Tx, Disable); /* Initialize UART *//*初始化串口配置*/ enRet = USART_UART_Init(M4_USART1, &stcInitCfg); if (enRet != Ok)while (1); /* Set baudrate *//*設置串口波特率*/ enRet = USART_SetBaudrate(M4_USART1, USART1_BAUDRATE); if (enRet != Ok)while (1); /* Set USART RX IRQ *//*設置串口接收中斷*/ stcIrqRegiCfg.enIRQn = Int000_IRQn;//設置中斷向量 stcIrqRegiCfg.pfnCallback = &Usart1RxIrqCallback;//設置中斷回調函數 stcIrqRegiCfg.enIntSrc = INT_USART1_RI;//中斷名稱 enIrqRegistration(&stcIrqRegiCfg); NVIC_SetPriority(stcIrqRegiCfg.enIRQn, DDL_IRQ_PRIORITY_DEFAULT);//設置中斷優先級
NVIC_ClearPendingIRQ(stcIrqRegiCfg.enIRQn); NVIC_EnableIRQ(stcIrqRegiCfg.enIRQn); /* Set USART RX error IRQ *//*設置串口接收錯誤中斷*/ stcIrqRegiCfg.enIRQn = Int001_IRQn; stcIrqRegiCfg.pfnCallback = &Usart1ErrIrqCallback; stcIrqRegiCfg.enIntSrc = INT_USART1_EI; enIrqRegistration(&stcIrqRegiCfg); NVIC_SetPriority(stcIrqRegiCfg.enIRQn, DDL_IRQ_PRIORITY_DEFAULT); NVIC_ClearPendingIRQ(stcIrqRegiCfg.enIRQn); NVIC_EnableIRQ(stcIrqRegiCfg.enIRQn); /*Enable RX && RX interupt function && UsartTx*/ USART_FuncCmd(M4_USART1, UsartRx, Enable);//使能接收 USART_FuncCmd(M4_USART1, UsartRxInt, Enable);//使能接收中斷 USART_FuncCmd(M4_USART1, UsartTx, Enable);//使能發送 }
usart.h
#ifndef USART_H_ #define USART_H_ #ifndef USART_C_ #define USART_C_ extern #else #define USART_C_ #endif #include "hc32_ddl.h" /* USART1 baudrate definition */ #define USART1_BAUDRATE (115200ul) /* USART1 TX Port/Pin definition */ #define USART1_TX_PORT (PortA) #define USART1_TX_PIN (Pin09) /* USART1 RX Port/Pin definition */ #define USART1_RX_PORT (PortA) #define USART1_RX_PIN (Pin10) void usart_init(void); #endif
2.在頭文件里面設置串口1波特率,還有使用哪個引腳作為串口1的發送和接收引腳
我配置了波特率為115200; PA9作為串口1的發送數據引腳; PA10作為串口1的串口接收引腳
3.串口基本的配置
4,配置串口中斷接收回調函數
注意:中斷向量有144個: Int000_IRQn, Int001_IRQn, Int002_IRQn .... Int142_IRQn, Int143_IRQn;數字越小,越優先執行
所謂中斷向量實際上就是中斷地址,Int000_IRQn, Int001_IRQn .... Int143_IRQn 都是代表不同的中斷地址.
程序執行中斷的時候是從Int000_IRQn, Int001_IRQn .... Int143_IRQn 依次執行.
設置中斷向量其實就是把這個回調函數放到相應的中斷地址上執行,所以每個中斷必須設置不同的中斷向量.
下面是把串口接收中斷函數放到了 Int000_IRQn, 就是說運行 Int000_IRQn地址就是執行串口接收中斷函數
-------------------------------------------------------------------------
下面還有個中斷優先級,中斷優先級共15個
NVIC_SetPriority(stcIrqRegiCfg.enIRQn, DDL_IRQ_PRIORITY_DEFAULT);//設置中斷優先級
中斷優先級控制着中斷嵌套優先的順序,
假設串口1接收中斷向量是Int000_IRQn, 中斷優先級是 2
假設串口2接收中斷向量是Int001_IRQn, 中斷優先級也是 2
假設同時來中斷,因為他們的中斷優先級是一樣的,那么就會對比中斷向量, 所以就會先執行串口1,再執行串口2;
--------------------------------------------------------------------------
假設串口1接收中斷向量是Int000_IRQn, 中斷優先級是 2
假設串口2接收中斷向量是Int001_IRQn, 中斷優先級是 1
假設同時來中斷,串口2的中斷優先級大於串口1, 所以就會先執行串口2,再執行串口1;
假設串口1在執行中斷,串口2來了中斷, 由於串口2的中斷優先級大於串口1, 所以也會去執行串口2,再執行串口1;
4,配置串口接收錯誤中斷回調函數
這個應該是固定處理形式,然后應該可以去掉.
5.使能
注意!要一句一句寫!不要用 USART_FuncCmd(M4_USART1, UsartRx | XXXX | XXXX , Enable); 不可以這樣子用
注意!要一句一句寫!不要用 USART_FuncCmd(M4_USART1, UsartRx | XXXX | XXXX , Enable); 不可以這樣子用
注意!要一句一句寫!不要用 USART_FuncCmd(M4_USART1, UsartRx | XXXX | XXXX , Enable); 不可以這樣子用
6.測試每隔一段時間發送一個字符1
//發送字符1 USART_SendData(M4_USART1, '1'); //等待串口發送完成 while (Reset == USART_GetStatus(M4_USART1, UsartTxEmpty));
7.對於一般的用戶接收數據呢用戶可以按照自己的習慣去寫就可以了
增加空閑中斷 (空閑中斷需要用到定時器,在后面的章節介紹)