本文主要是介绍华大HC32F4A0/F460串口裸机驱动,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
使用了DMA以及中断,测试比较简单,代码是F460上面用的,今天试了F4A0也可以直接用,需要提前初始化DMA,INT,以及IO复用功能;
/************************************************************************************************************** 文件名: uart.c* 功能: HC32F4A0 UART通讯支持* 作者: cp1300@139.com* 创建时间: 2021-11-19* 最后修改时间: 2021-11-19* 详细: 2021-09-12:修复设置串口传输位数bug,正常要设置CR1 BIT12位为0
*************************************************************************************************************/
#include "hc32f4a0_system.h"
#include "uart.h"
#include "typedef.h"//串口中断接收函数
#if !UART_DMA_EN
__inline static void UARTx_IRQHandler(UART_CH_Type ch); //串口中断处理
static void UART1_RX_IRQHandler(void) {UARTx_IRQHandler(UART_CH1);} //串口1接收中断服务程序
static void UART2_RX_IRQHandler(void) {UARTx_IRQHandler(UART_CH2);} //串口2接收中断服务程序
static void UART3_RX_IRQHandler(void) {UARTx_IRQHandler(UART_CH3);} //串口3接收中断服务程序
static void UART4_RX_IRQHandler(void) {UARTx_IRQHandler(UART_CH4);} //串口4接收中断服务程序//中断函数集合
static const void *scg_pUartIrqHandle[UART_ChMax] =
{(const void *)UART1_RX_IRQHandler, (const void *)UART2_RX_IRQHandler, (const void *)UART3_RX_IRQHandler, (const void *)UART4_RX_IRQHandler};//串口中断所占用的中断线
static const IRQn_Type scg_UartIrqType[UART_ChMax] =
{SYS_IRQ_UART1_RX_NUM, SYS_IRQ_UART2_RX_NUM, SYS_IRQ_UART3_RX_NUM, SYS_IRQ_UART4_RX_NUM}; //串口中断源
static const INT_SOURCE_TYPE scg_UartIntSourceType[UART_ChMax] =
{SYS_INT_USART1_RI, SYS_INT_USART2_RI, SYS_INT_USART3_RI, SYS_INT_USART4_RI};
#endif //UART_DMA_EN//时钟使能
static const SYS_DEV_CLOCK scg_UARTx_DeviceClockEnable[UART_ChMax] =
{DEV_USART1, DEV_USART2, DEV_USART3, DEV_USART4};
//串口基址
static const u32 scg_UARTx_Base[UART_ChMax] = {UART1_BASE, UART2_BASE, UART3_BASE, UART4_BASE}; //DAM通道设置
#if UART_DMA_EN
#include "dma.h"
static const DMAx_CH_TYPE scg_UART_RxDMAChannel[4] = {DMA2_CH1, DMA2_CH2, DMA2_CH3,DMA2_CH4}; //接收通道
static const u32 scg_UART_RX_DR_ADDR[4] = {UART1_BASE + 0x04 + 2, UART2_BASE + 0x04 + 2, UART3_BASE + 0x04 + 2, UART4_BASE + 0x04 + 2}; //UART接收寄存器地址
static const u32 scg_UART_TX_DR_ADDR[4] = {UART1_BASE + 0x04 + 0, UART2_BASE + 0x04 + 0, UART3_BASE + 0x04 + 0, UART4_BASE + 0x04 + 0}; //UART发送寄存器地址
static const INT_SOURCE_TYPE scg_UART_Rx_DMA_Trigger[4] = {SYS_INT_USART1_RI, SYS_INT_USART2_RI, SYS_INT_USART3_RI, SYS_INT_USART4_RI}; //UART接收DMA触发源
static const INT_SOURCE_TYPE scg_UART_Tx_DMA_Trigger[4] = {SYS_INT_USART1_TI, SYS_INT_USART2_TI, SYS_INT_USART3_TI, SYS_INT_USART4_TI}; //UART发送DMA触发源
#endif //UART_DMA_EN//相关UART状态结构
typedef struct
{bool isNewDataFlag; //接收到新数据bool isBuffFull; //接收Buff满bool isIntRx; //是否开启中断接收u8 *RxBuff; //接收Buff指针u16 RxBuffSize; //接收缓冲区大小,一帧数据大小u16 UartRxCnt; //接收数据计数器u8 TempData; //用于接收溢出后读取数据寄存器,清除读取数据标志
} UartRx_TypeDef;
static UartRx_TypeDef sg_UartRx[UART_ChMax];/*************************************************************************************************************************
*函数 : bool UARTx_Config(UART_CH_Type ch,UART_Config_TypeDef * cfg)
*功能 : 串口配置
*参数 : ch:串口号;cfg:配置结构体
*返回 : TRUE:配置成功; FALSE: 配置失败
*依赖 : 底层宏定义
*作者 : cp1300@139.com
*时间 : 2021-11-19
*最后修改时间 : 2021-11-19
*说明 : 配置前最好确保数据已经发送完成,没有数据正在发送
*************************************************************************************************************************/
bool UARTx_Config(UART_CH_Type ch,UART_Config_TypeDef * cfg)
{u32 temp;UART_TypeDef *UARTx;if(ch > (UART_ChMax - 1)) return FALSE; //端口号超出范围UARTx = (UART_TypeDef *) scg_UARTx_Base[ch]; //获取设备基址temp = UARTx->CR1;//奇偶校验switch(cfg->OddEvenVerify) {case UART_ODD: //奇校验{temp |= BIT10; //开启校验temp |= BIT9; //奇校验}break;case UART_EVEN: //偶校验{temp |= BIT10; //开启校验temp &= ~BIT9; //偶校验}break;default://无校验{temp &= ~BIT10; //关闭校验}break; }//数据长度if(cfg->DataBitWidth == UART_DATA_8BIT) //数据位长度设置8bit{temp &= ~BIT12;}else{temp |= BIT12;}UARTx->CR1 = temp;//停止位temp = UARTx->CR2;if(cfg->StopBitWidth != UART_STOP_1BIT) //不止1个停止位{temp |= BIT13; //2个停止位}else{temp &= ~BIT13; //1个停止位}UARTx->CR2 = temp;return TRUE;
}/*************************************************************************************************************************
* 函数 : void UARTx_SetBaudRate(UART_CH_Type ch,u32 baud)
* 功能 : 串口波特率设置
* 参数 : ch:通道选择,baud:波特率,如9600,115200等等
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 2021-11-19
* 最后修改时间 : 2021-11-19
* 说明 : 注意 DIV_Integer[7:0]只能 在 TE=0&RE=0(发送 /接收 禁止 )时设定DIV_Fraction[6:0]只能 在 TE=0&RE=0(发送 /接收 禁止 )时设定, 而且仅在 FBME=1时设定值 有效
*************************************************************************************************************************/
bool UARTx_SetBaudRate(UART_CH_Type ch,u32 baud)
{u8 Integer;u8 Fraction;UART_TypeDef *UARTx;float ftemp;u32 temp; //PCLK频率if(ch > (UART_ChMax - 1)) return FALSE; //端口号超出范围UARTx = (UART_TypeDef *) scg_UARTx_Base[ch]; //获取设备基址temp = SYS_GetPCLK1Speed(); //获取PCLK1时钟速度ftemp = (double)temp/(8*baud);if(ftemp < 1 || ftemp >= 256) return FALSE; //时钟范围错误Integer = ftemp; //整数分频//计算实际的波特率,由于整数分频存在误差,最终波特率只会偏大,不会偏小temp /= 8;temp /= Integer;//计算需要的波特率与实际波特率比值ftemp = baud; //用目标波特率除以实际波特率,得到偏差比值,这个比值只会小于1,并且会接近1ftemp /= temp; //得到了比值乘以256 - 128 就是最终的小数补偿值ftemp *= 256.0f;ftemp -= 128.0f;Integer -= 1; //实际整数分频-1//小数分频计算if(ftemp < 1){ftemp = 0;UARTx->CR1 &= ~BIT29; //FBME=0关闭小数波特率功能}else{UARTx->CR1 |= BIT29; //FBME=1使能小数波特率功能}Fraction = ftemp; //计算得到最终的小数分频temp = Integer;temp <<= 8;temp |= Fraction&0x7F;UARTx->PR = 0; //预分频寄存器为0UARTx->BRR = temp;return TRUE;
}/*************************************************************************************************************************
* 函数 : bool UARTx_Init(UART_CH_Type ch,u32 Speed,bool isEnableRx)
* 功能 : 串口初始化
* 参数 : ch:通道选择,0->usart1,Speed:串口速度,isEnableRx:是否使能接收
* 返回 : TRUE:成功,FALSE:失败
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 2021-11-19
* 最后修改时间 : 2021-06-23
* 说明 :
*************************************************************************************************************************/
bool UARTx_Init(UART_CH_Type ch,u32 Speed,bool isEnableRx)
{UART_Config_TypeDef cfg;UART_TypeDef *UARTx;if(ch > (UART_ChMax - 1)) return FALSE; //端口号超出范围UARTx = (UART_TypeDef *) scg_UARTx_Base[ch]; //获取设备基址SYS_DeviceClockEnable(scg_UARTx_DeviceClockEnable[ch], TRUE); //外设时钟使能或关闭控制UARTx->CR1 = 0xFFFFFFF3ul;UARTx->CR1 = 0x80000000ul;UARTx->CR1 = 0; //控制器寄存器复位UARTx->CR2 = 0;UARTx->CR3 = 0;UARTx->CR1 |= BIT31; //检测方式为RX下降沿//UARTx->CR1 |= BIT30; //使能数字滤波UARTx->CR1 |= BIT20|BIT19|BIT17|BIT16; //清除各种标志UARTx->CR1 |= BIT15; //过采样为8位//配置cfg.DataBitWidth = UART_DATA_8BIT; //数据宽度8cfg.OddEvenVerify = UART_VERIFY_NULL; //无奇偶校验cfg.StopBitWidth = UART_STOP_1BIT; //1个停止位if(UARTx_SetBaudRate(ch, Speed) == FALSE) return FALSE; //设置波特率if(UARTx_Config(ch, &cfg) == FALSE) return FALSE; //设置串口数据格式sg_UartRx[ch].isIntRx = FALSE; //没有开启中断接收//IO初始化//使能了接收if(isEnableRx){
#if(UART_DMA_EN)UARTx->CR1 |= BIT2; //接收使能
#else //中断方式 UARTx->CR1 |= BIT5; //接收中断使能INTC_RegisterIRQHandler(scg_UartIrqType[ch], scg_UartIntSourceType[ch], (void (*)(void))scg_pUartIrqHandle[ch]);//注册中断服务程序NVIC_ClearPendingIRQ(scg_UartIrqType[ch]);NVIC_SetPriority(scg_UartIrqType[ch], UART_INT_PRIO);NVIC_EnableIRQ(scg_UartIrqType[ch]);UARTx->CR1 |= BIT2; //接收使能
#endif //UART_DMA_ENsg_UartRx[ch].isIntRx = TRUE; //开启了接收}//发送使能UARTx->CR1 |= BIT3;return TRUE;
}/*************************************************************************************************************************
* 函数 : void UARTx_SendByte(UART_CH_Type ch,u8 data)
* 功能 : UART单字节发送
* 参数 : ch:通道号,dataL:要发送的数据
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 2021-11-19
* 最后修改时间 : 2021-11-19
* 说明 : 单字节发送不要使用DMA,浪费2021-07-28:解决不能while空循环,V6编译器会优化掉问题,后面加个nop即可;
*************************************************************************************************************************/
void UARTx_SendByte(UART_CH_Type ch,u8 data)
{UART_TypeDef *UARTx;if(ch > (UART_ChMax - 1)) return; //端口号超出范围UARTx = (UART_TypeDef *) scg_UARTx_Base[ch]; //获取设备基址while((UARTx->SR & BIT7)==0) nop; //等待TX发送寄存器为空UARTx->DR = data; //发送数据-写到带发送寄存器,并不会等待数据发送完成
}/*************************************************************************************************************************
* 函数 : void UARTx_SendData(UART_CH_Type ch,u8 *tx_buff,u16 byte_number)
* 功能 : UART数据发送函数
* 参数 : ch:通道号,tx_buff:发送缓冲区,byte_number:需要发送的字节
* 返回 : 无
* 依赖 : void UART_SendByte(u8 ch,u8 data)
* 作者 : cp1300@139.com
* 时间 : 2021-11-19
* 最后修改时间 : 2021-11-19
* 说明 :
*************************************************************************************************************************/
void UARTx_SendData(UART_CH_Type ch,u8 *pTxBuff,u16 DataLen)
{u16 i;
#if(UART_DMA_EN) //使能DMA发送 int dma_ch;UART_TypeDef *UARTx;bool isNotDMA = FALSE;
#endif if(ch > (UART_ChMax - 1)) return; //端口号超出范围#if(UART_DMA_EN) //使能DMA发送UARTx = (UART_TypeDef *) scg_UARTx_Base[ch]; //获取设备基址dma_ch = DMA_GetIdleChannel();//获取一个DMA空闲通道(用完后需要释放)//uart_printf("dma_ch=%d\r\n", dma_ch);if(dma_ch < 0) //DMA获取失败,直接用字节发送{isNotDMA = TRUE;}else //DMA发送{if(DataLen < UART_DMA_TX_MIN) {isNotDMA = TRUE;}else //DMA发送{while((UARTx->SR & BIT7)==0); //等待TX发送寄存器为空DMA_MemoryToPeripheralConfig((DMAx_CH_TYPE) dma_ch, (u32)&pTxBuff[1], scg_UART_TX_DR_ADDR[ch], DMA_SIZE_8BIT, DataLen-1, scg_UART_Tx_DMA_Trigger[ch], TRUE);//DMA存储器到外设传输配置UARTx_SendByte(ch, pTxBuff[0]); //初始化DMA后不会被触发发送,只有先发送一条数据,让发送寄存器空从无效变为有效,之后就会触发DMA发送if(DMA_WaitMemComplete((DMAx_CH_TYPE) dma_ch, (u32)DataLen*2) == FALSE) //等待存储器DMA传输完成{u16 cnt = DMA_GetCompleteResidualCnt((DMAx_CH_TYPE) dma_ch);DEBUG("dma_ch=%d 发送超时 cnt=%d\r\n",dma_ch, cnt);DMA_StopTrans((DMAx_CH_TYPE) dma_ch); //传输超时,强制关闭 DMA 传输}DMA_ReleaseChannel(dma_ch);//释放当前使用的通道} }if(isNotDMA) //不需要用DMA发送{for(i = 0;i < DataLen;i++) //循环发送,直至发送完毕{UARTx_SendByte(ch, pTxBuff[i]);}}#else for(i = 0;i < DataLen;i++) //循环发送,直至发送完毕{UARTx_SendByte(ch, pTxBuff[i]);}#endif //UART_DMA_EN#if (!UART_TX_TO_FIFI) //要求等待数据发送完成UARTx_WaitSendComplete(ch); //等待数据发送完成-从串口发送完成
#endif //UART_TX_TO_FIFI
}/*************************************************************************************************************************
* 函数 : void UARTx_WaitSendComplete(UART_CH_Type ch)
* 功能 : 等待数据发送完成-从串口发送完成
* 参数 : ch:通道号
* 返回 : 无
* 依赖 : 无
* 作者 : cp1300@139.com
* 时间 : 2021-11-19
* 最后修改时间 : 2021-11-19
* 说明 :
*************************************************************************************************************************/
void UARTx_WaitSendComplete(UART_CH_Type ch)
{UART_TypeDef *UARTx;if(ch > (UART_ChMax - 1)) return; //端口号超出范围UARTx = (UART_TypeDef *) scg_UARTx_Base[ch]; //获取设备基址while((UARTx->SR & BIT6) == 0) //等待发送完成{SYS_DelayMS(1);}
}/*************************************************************************************************************************
* 函数 : void UARTx_SendString(UART_CH_Type ch,char *pString)
* 功能 : UART发送字符串
* 参数 : ch:通道号pString:字符串指针
* 返回 : 无
* 依赖 : void UART_SendByte(u8 ch,u8 data)
* 作者 : cp1300@139.com
* 时间 : 2021-11-19
* 最后修改时间 : 2021-11-19
* 说明 :
*************************************************************************************************************************/
#include "string.h"
void UARTx_SendString(UART_CH_Type ch,char *pString)
{ if(ch > (UART_ChMax - 1)) return; //端口号超出范围UARTx_SendData(ch, (u8 *)pString, strlen(pString));
}/*************************************************************************************************************************
* 函数 : bool UARTx_GetNewDataFlag(UART_CH_Type ch)
* 功能 : 获取串口新数据标志
* 参数 : ch:通道选择
* 返回 : TRUE:成功,FALSE:失败
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 2021-11-19
* 最后修改时间 : 2021-11-19
* 说明 : 用于判断是否有新的数据,会清除掉新数据标志的
*************************************************************************************************************************/
bool UARTx_GetNewDataFlag(UART_CH_Type ch)
{UART_TypeDef *UARTx;if(ch > (UART_ChMax - 1)) return FALSE; //端口号超出范围UARTx = (UART_TypeDef *) scg_UARTx_Base[ch]; //获取设备基址if(sg_UartRx[ch].isIntRx == TRUE) //开启了中断接收{if(sg_UartRx[ch].isNewDataFlag == TRUE) //有新数据{sg_UartRx[ch].isNewDataFlag = FALSE; //清除标志return TRUE; //返回有新数据}}else //没开启中断接收{if((UARTx->SR & BIT5) == 0) //接收FIFO不为空{return TRUE;}}return FALSE;
}/*************************************************************************************************************************
* 函数 : bool UARTx_GetRxBuffFullFlag(UART_CH_Type ch)
* 功能 : 获取串口接收缓冲区满标志
* 参数 : ch:通道选择
* 返回 : TRUE:成功,FALSE:失败
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 2021-11-19
* 最后修改时间 : 2021-11-19
* 说明 : 用于判断接收缓冲区是否满,会清除标志
*************************************************************************************************************************/
bool UARTx_GetRxBuffFullFlag(UART_CH_Type ch)
{if(ch > (UART_ChMax - 1)) return FALSE; //端口号超出范围if(sg_UartRx[ch].isBuffFull == TRUE) //缓冲区已满{sg_UartRx[ch].isBuffFull = FALSE; //清除满标志return TRUE;}return FALSE;
}/*************************************************************************************************************************
* 函数 : u8 UARTx_GetNewData(UART_CH_Type ch)
* 功能 : 获取串口新数据
* 参数 : ch:通道选择
* 返回 : 收到的数据
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 2021-11-19
* 最后修改时间 : 2021-11-19
* 说明 : 用于接收一个字节数据
*************************************************************************************************************************/
u8 UARTx_GetNewData(UART_CH_Type ch)
{UART_TypeDef *UARTx;if(ch > (UART_ChMax - 1)) return FALSE; //端口号超出范围UARTx = (UART_TypeDef *) scg_UARTx_Base[ch]; //获取设备基址return UARTx->DR >> 16; //返回数据
}/*************************************************************************************************************************
* 函数 : void UARTx_SetRxBuff(UART_CH_Type ch,u8 *RxBuff,u16 RxBuffSize)
* 功能 : 设置串口接收缓冲区
* 参数 : ch:通道选择,RxBuffSize:缓冲区大小,RxBuff:缓冲区指针
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 2021-11-19
* 最后修改时间 : 2021-11-19
* 说明 : 一定要设置,否则开启中断接收时可能会异常
*************************************************************************************************************************/
void UARTx_SetRxBuff(UART_CH_Type ch,u8 *RxBuff,u16 RxBuffSize)
{#ifdef _UCOS_II_OS_CPU_SR cpu_sr;#endif //_UCOS_II_if(ch > UART_ChMax - 1) //判断端口是否超出范围return;#if UART_DMA_ENDMA_PeripheralToMemoryConfig(scg_UART_RxDMAChannel[ch], (u32)RxBuff, scg_UART_RX_DR_ADDR[ch], DMA_SIZE_8BIT, RxBuffSize, scg_UART_Rx_DMA_Trigger[ch], TRUE); //DMA外设到存储器传输配置#endif //UART_DMA_EN#ifdef _UCOS_II_OS_ENTER_CRITICAL();#endif //_UCOS_II_sg_UartRx[ch].RxBuffSize = RxBuffSize; //设置缓冲区大小sg_UartRx[ch].RxBuff = RxBuff; //设置缓冲区指针#if !UART_DMA_EN sg_UartRx[ch].UartRxCnt = 0; //计数器清零#endif //!UART_DMA_EN#ifdef _UCOS_II_OS_EXIT_CRITICAL();#endif //_UCOS_II_
}/*************************************************************************************************************************
* 函数 : u32 UARTx_GetRxCnt(UART_CH_Type ch)
* 功能 : 获取串口接收数据计数器
* 参数 : ch:通道选择
* 返回 : 接收到的数据数量
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 2021-11-19
* 最后修改时间 : 2021-11-19
* 说明 : 无
*************************************************************************************************************************/
u32 UARTx_GetRxCnt(UART_CH_Type ch)
{ if(ch > (UART_ChMax - 1)) return 0; //端口号超出范围#if UART_DMA_ENreturn sg_UartRx[ch].RxBuffSize - DMA_GetCompleteResidualCnt(scg_UART_RxDMAChannel[ch]);
#elsereturn sg_UartRx[ch].UartRxCnt; //返回计数值
#endif //UART_DMA_EN
}/*************************************************************************************************************************
* 函数 : void UARTx_ClearRxCnt(UART_CH_Type ch)
* 功能 : 清除串口接收数据计数器
* 参数 : ch:通道选择
* 返回 : 无
* 依赖 : 底层宏定义
* 作者 : cp1300@139.com
* 时间 : 2021-11-19
* 最后修改时间 : 2021-11-19
* 说明 : 无
*************************************************************************************************************************/
void UARTx_ClearRxCnt(UART_CH_Type ch)
{
#if UART_DMA_EN UART_TypeDef *UARTx;
#endif //UART_DMA_ENif(ch > (UART_ChMax - 1)) return; //端口号超出范围#if UART_DMA_ENUARTx = (UART_TypeDef *) scg_UARTx_Base[ch]; //获取设备基址DMA_StartTrans(scg_UART_RxDMAChannel[ch], scg_UART_RX_DR_ADDR[ch], (u32)sg_UartRx[ch].RxBuff, sg_UartRx[ch].RxBuffSize); UARTx->CR1 |= 0x1B << 16; //清除中断标志{u8 temp = UARTx->DR>>16; //取出读到的数据temp = temp;}#elsesg_UartRx[ch].UartRxCnt = 0; //计数器清零
#endif //UART_DMA_EN
}#if !UART_DMA_EN
//用于串口中断中读取数据
__inline static void UARTx_ReadRxData(UART_CH_Type ch, UART_TypeDef *UARTx)
{//while(UARTx->SR & BIT5) //接收FIFO中有数据,循环读取{if((sg_UartRx[ch].RxBuffSize) > 0 && (sg_UartRx[ch].UartRxCnt < sg_UartRx[ch].RxBuffSize)) //接收缓冲区大于0,并且没有满{(sg_UartRx[ch].RxBuff)[(sg_UartRx[ch].UartRxCnt) ++] = UARTx->DR>>16; //将数据存放到缓冲区if(sg_UartRx[ch].UartRxCnt == sg_UartRx[ch].RxBuffSize) //缓冲区已满{//sg_UartRx[ch].UartRxCnt = 0; //接收计数器清零sg_UartRx[ch].isBuffFull = TRUE; //缓冲区已满标志} }else //缓冲区满了,清除接收到的数据{sg_UartRx[ch].TempData = UARTx->DR>>16;}} //UARTx_SendByte(ch, sg_UartRx[ch].TempData); //调试,将收到的数据发送出去
}//串口中断处理
__inline static void UARTx_IRQHandler(UART_CH_Type ch)
{UART_TypeDef *UARTx;UARTx = (UART_TypeDef *) scg_UARTx_Base[ch]; //获取设备基址if(UARTx->SR & BIT5) //FIFO收到指定数据的数据了{UARTx_ReadRxData(ch, UARTx);}UARTx->CR1 |= BIT17|BIT16|BIT19|BIT20; //清除中断
}#endif //UART_DMA_EN
/************************************************************************************************************** 文件名: uart.h* 功能: HC32F4A0 UART通讯支持* 作者: cp1300@139.com* 创建时间: 2021-11-19* 最后修改时间: 2021-11-19* 详细:
*************************************************************************************************************/
#ifndef _UART_H_
#define _UART_H_
#include "hc32f4a0_system.h"/***********************配置相关************************/
#define UART_TX_TO_FIFI 1 //1:数据发送到发送FIFO则认为发送完成; 0:数据从移位寄存器发送完成则认为发送完成
#define UART_ChMax 4 //串口通道数量
#define UART_DMA_EN 1 //释放使能DMA
#define UART_INT_PRIO SYS_INT_UART_RX_PRO //中断优先级
#define UART_DMA_TX_MIN 63 //使用DMA发送最少的数据,少于这个值不调用DMA,数据太少,使用DMA效率不高,但是至少3个字节以上
/*********************************************************///串口选择,串口0开始,到串口10
typedef enum
{UART_CH1 = 0, //UART1UART_CH2 = 1, //UART2UART_CH3 = 2, //UART3UART_CH4 = 3, //UART4UART_CH5 = 4, //UART5UART_CH6 = 5, //UART6UART_CH7 = 6, //UART7UART_CH8 = 7, //UART8UART_CH9 = 8, //UART9UART_CH10 = 9, //UART10
}UART_CH_Type;//UART配置相关结构定义
typedef struct
{u8 OddEvenVerify; //奇偶校验,奇,偶,无u8 StopBitWidth; //停止位位宽1,2u8 DataBitWidth; //数据位宽度8,9
} 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个停止位
//数据位数
#define UART_DATA_8BIT 0 //8位数据长度
#define UART_DATA_9BIT 1 //8位数据长度//相关API
bool UARTx_Init(UART_CH_Type ch,u32 Speed, bool isEnableRx); //串口初始化
void UARTx_SendByte(UART_CH_Type ch,u8 data); //UART单字节发送
void UARTx_SendData(UART_CH_Type ch,u8 *pTxBuff,u16 DataLen); //UART数据发送函数
void UARTx_WaitSendComplete(UART_CH_Type ch); //等待数据发送完成-从串口发送完成
void UARTx_SendString(UART_CH_Type ch,char *pString); //UART发送字符串
bool UARTx_GetNewDataFlag(UART_CH_Type ch); //获取串口新数据标志
bool UARTx_GetRxBuffFullFlag(UART_CH_Type ch); //获取串口接收缓冲区满标志
u8 UARTx_GetNewData(UART_CH_Type ch); //获取串口新数据
void UARTx_SetRxBuff(UART_CH_Type ch,u8 *RxBuff,u16 RxBuffSize); //设置串口接收缓冲区
void UARTx_ClearRxInt(UART_CH_Type ch); //清除串口接收中断标志
u32 UARTx_GetRxCnt(UART_CH_Type ch); //获取串口接收数据计数器
void UARTx_ClearRxCnt(UART_CH_Type ch); //清除串口接收数据计数器#endif //_UART_H_
//UART========================================================================================================
#define UART1_BASE (0x4001CC00UL) //寄存器基址
#define UART2_BASE (0x4001D000UL) //寄存器基址
#define UART3_BASE (0x4001D400UL) //寄存器基址
#define UART4_BASE (0x4001D800UL) //寄存器基址
#define UART5_BASE (0x4001DC00UL) //寄存器基址
#define UART6_BASE (0x40020C00UL) //寄存器基址
#define UART7_BASE (0x40021000UL) //寄存器基址
#define UART8_BASE (0x40021400UL) //寄存器基址
#define UART9_BASE (0x40021800UL) //寄存器基址
#define UART10_BASE (0x40021C00UL) //寄存器基址typedef struct
{vu32 SR; //状态寄存器vu32 DR; //数据寄存器vu32 BRR; //波特率寄存器vu32 CR1; //控制寄存器1vu32 CR2; //控制寄存器2vu32 CR3; //控制寄存器3vu32 PR; //预分配寄存器vu32 LBMC; //LIN波特率测量计数寄存器
}UART_TypeDef;#define UART1 ((UART_TypeDef *) UART1_BASE)
#define UART2 ((UART_TypeDef *) UART2_BASE)
#define UART3 ((UART_TypeDef *) UART3_BASE)
#define UART4 ((UART_TypeDef *) UART4_BASE)
#define UART5 ((UART_TypeDef *) UART5_BASE)
#define UART6 ((UART_TypeDef *) UART6_BASE)
#define UART7 ((UART_TypeDef *) UART7_BASE)
#define UART8 ((UART_TypeDef *) UART8_BASE)
#define UART9 ((UART_TypeDef *) UART9_BASE)
#define UART10 ((UART_TypeDef *) UART10_BASE)
//测试
n(void)
{u32 i = 0;SYS_GPIOx_OneInit(GPIOE, 6, OUT_PP, GPIO_DRV_0);LED = 0;UARTx_Init(UART_PRINTF_CH, 256000, TRUE);SYS_GPIOx_SetAF(GPIOE, 1, 32);SYS_GPIOx_SetAF(GPIOE, 0, 33);uart_printf("hello world!\r\n");while (1){LED = !LED;delay_ms();uart_printf("%u\r\n", i++);}
}
这篇关于华大HC32F4A0/F460串口裸机驱动的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!