华大HC32F4A0/F460串口裸机驱动

2023-11-10 13:11

本文主要是介绍华大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串口裸机驱动的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/382834

相关文章

Linux_kernel驱动开发11

一、改回nfs方式挂载根文件系统         在产品将要上线之前,需要制作不同类型格式的根文件系统         在产品研发阶段,我们还是需要使用nfs的方式挂载根文件系统         优点:可以直接在上位机中修改文件系统内容,延长EMMC的寿命         【1】重启上位机nfs服务         sudo service nfs-kernel-server resta

驱动(RK3588S)第七课时:单节点设备树

目录 需求一、设备树的概念1、设备树的后缀名:2、设备树的语法格式3、设备树的属性(重要)4、设备树格式举例 二、设备树所用函数1、如何在内核层种获取设备树节点:2、从设备树上获取 gpio 口的属性3、获取节点上的属性只针对于字符串属性的4、函数读取 np 结点中的 propname 属性的值,并将读取到的 u32 类型的值保存在 out_value 指向的内存中,函数的返回值表示读取到的

驱动安装注册表指令

HKCR: HKEY_CLASSES_ROOT HKCU: HKEY_CURRENT_USER HKLM: HKEY_LOCAL_MACHINE HKU: HEKY_USER HER: 相对根键

UMDF驱动安装

VS2013 + WDF8.1,UMDF驱动选择User Mode Driver,不要选User Mode Driver 2.0,否则Win7安装有问题,如图 另外,在驱动安装时不要忘记WUDFUpdate_<主版本号><次版本号>.dll文件,具体文件名在INF中查找。此文件可在WDF的安装目录中找到。注意:在WDF的安装目录中会有3个WUDFUpdate_xxx.dll文件,x86,x6

安卓开发板_联发科MTK开发评估套件串口调试

串口调试 如果正在进行lk(little kernel ) 或内核开发,USB 串口适配器( USB 转串口 TTL 适配器的简称)对于检查系统启动日志非常有用,特别是在没有图形桌面显示的情况下。 1.选购适配器 常用的许多 USB 转串口的适配器,按芯片来分,有以下几种: CH340PL2303CP2104FT232 一般来说,采用 CH340 芯片的适配器,性能比较稳定,价

VB和51单片机串口通信讲解(只针对VB部分)

标记:该篇文章全部搬自如下网址:http://www.crystalradio.cn/thread-321839-1-1.html,谢谢啦            里面关于中文接收的部分,大家可以好好学习下,题主也在研究中................... Commport;设置或返回串口号。 SettingS:以字符串的形式设置或返回串口通信参数。 Portopen:设置或返回串口

电脑驱动分类

电脑驱动程序(驱动程序)是操作系统与硬件设备之间的桥梁,用于使操作系统能够识别并与硬件设备进行通信。以下是常见的驱动分类: 1. 设备驱动程序 显示驱动程序:控制显卡和显示器的显示功能,负责图形渲染和屏幕显示。 示例:NVIDIA、AMD 显示驱动程序。打印机驱动程序:允许操作系统与打印机通信,控制打印任务。 示例:HP、Canon 打印机驱动程序。声卡驱动程序:管理音频输入和输出,与声卡硬件

麒麟系统安装GPU驱动

1.nvidia 1.1显卡驱动 本机显卡型号:nvidia rtx 3090 1.1.1下载驱动 打开 https://www.nvidia.cn/geforce/drivers/ 也可以直接使用下面这个地址下载 https://www.nvidia.com/download/driverResults.aspx/205464/en-us/ 1.1.3安装驱动 右击,

windows10 卸载网络驱动以及重新安装

右键桌面此电脑的图标,点击管理,设备管理器—网络适配器,找到下图中的驱动(不同的系统或者显卡会导致网卡驱动名称与下图不一样,多为Realtek开头),右键选择卸载设备,然后重启电脑,系统会自动重新安装驱动 新电脑首次安装驱动: 根据主板厂家,比如华硕,进入华硕官网,点击服务支持,点击下载中心,选择型号,点击右侧驱动程序和工具软件,选择windows版本,下载相应的驱动,下载完之后在对应文件中找

笔记整理—内核!启动!—kernel部分(1)驱动与内核的关系

首先,恭喜完成了uboot部分的内容整理,其次补充一点,uboot第一部分和第二部分的工作不是一定的,在不同的版本中,可能这个初始化早一点,那个的又放在了第二部分,版本不同,造成的工作顺序不同,但终归是要完成基本内容初始化并传参给kernel的。         那么至于驱动与内核的关系,用一张图来说明最适合不过:         驱动位于OS层的中下层与硬件相接。驱动是内