使用了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,并且会接近1
ftemp /= 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; //预分频寄存器为0
UARTx->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; //数据宽度8
cfg.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_EN
sg_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_EN
DMA_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_EN
return sg_UartRx[ch].RxBuffSize - DMA_GetCompleteResidualCnt(scg_UART_RxDMAChannel[ch]);
#else
return 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_EN
if(ch > (UART_ChMax - 1)) return; //端口号超出范围
#if UART_DMA_EN
UARTx = (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;
}
#else
sg_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, //UART1
UART_CH2 = 1, //UART2
UART_CH3 = 2, //UART3
UART_CH4 = 3, //UART4
UART_CH5 = 4, //UART5
UART_CH6 = 5, //UART6
UART_CH7 = 6, //UART7
UART_CH8 = 7, //UART8
UART_CH9 = 8, //UART9
UART_CH10 = 9, //UART10
}UART_CH_Type;
//UART配置相关结构定义
typedef struct
{
u8 OddEvenVerify; //奇偶校验,奇,偶,无
u8 StopBitWidth; //停止位位宽1,2
u8 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; //控制寄存器1
vu32 CR2; //控制寄存器2
vu32 CR3; //控制寄存器3
vu32 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++);
}
}
版权声明:本文为CSDN博主「cp1300」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/cp1300/article/details/121431121
暂无评论