您的当前位置:首页正文

华大HC32L196的串口中断发送数据方式

来源:九壹网

1.初始化

UART1_TX    GPIO_PA02

UART1_RX    GPIO_PA03

int32_t main(void)
{
    Uart1_Config();						//usrt1功能配置
	Uart1_PortInit();					//usrt1引脚配置
}
static void Uart1_Config(void)
{
    stc_uart_cfg_t    stcCfg;

    DDL_ZERO_STRUCT(stcCfg);
    
    ///< 开启外设时钟
    Sysctrl_SetPeripheralGate(SysctrlPeripheralUart1,TRUE);///<使能uart1模块时钟
    
    ///<UART Init
    stcCfg.enRunMode        = UartMskMode1;          ///<模式1
    stcCfg.enStopBit        = UartMsk1bit;           ///<1bit停止位
    stcCfg.enMmdorCk        = UartMskEven;           ///<偶检验
    stcCfg.stcBaud.u32Baud  = 9600;                  ///<波特率9600
    stcCfg.stcBaud.enClkDiv = UartMsk8Or16Div;       ///<通道采样分频配置
    stcCfg.stcBaud.u32Pclk  = Sysctrl_GetPClkFreq(); ///<获得外设时钟(PCLK)频率值
    Uart_Init(M0P_UART1, &stcCfg);                   ///<串口初始化
    
    ///<UART中断使能
    Uart_ClrStatus(M0P_UART1,UartRC);                ///<清接收请求
    Uart_ClrStatus(M0P_UART1,UartTC);                ///<清接收请求
    Uart_EnableIrq(M0P_UART1,UartRxIrq);             ///<使能串口接收中断
	Uart_DisableIrq(M0P_UART1,UartTxIrq);        	 ///<关闭串口发送中断    
    EnableNvic(UART1_3_IRQn, IrqLevel3, TRUE);       ///<系统中断使能

}
static void Uart1_PortInit(void)
{
    stc_gpio_cfg_t stcGpioCfg;
    
    DDL_ZERO_STRUCT(stcGpioCfg);
    
    Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio,TRUE); //使能GPIO模块时钟
    
	
	///<TX
    stcGpioCfg.enDir = GpioDirOut;		//端口方向配置 							输出
	stcGpioCfg.enPu = GpioPuEnable;		//端口上拉配置 							GPIO上拉
    stcGpioCfg.enCtrlMode = GpioAHB;	//端口输入输出寄存器总线控制模式配置	AHB 总线控制模式
    stcGpioCfg.enDrv = GpioDrvH;		//端口驱动能力配置 						GPIO高驱动能力
    stcGpioCfg.enOD = GpioOdDisable;	//端口开漏配置							GPIO开漏输出关闭
    stcGpioCfg.enPd = GpioPdDisable;	//端口下拉配置 							GPIO无下拉
    Gpio_Init(GpioPortA, GpioPin2, &stcGpioCfg);
    Gpio_SetAfMode(GpioPortA, GpioPin2, GpioAf1);          //配置TX
    
    ///<RX
    stcGpioCfg.enDir = GpioDirIn;		//端口方向配置 输入
	stcGpioCfg.enPu = GpioPuEnable;		//端口方向配置 GPIO上拉
    stcGpioCfg.enCtrlMode = GpioAHB;	//端口输入输出寄存器总线控制模式配置	AHB 总线控制模式
    stcGpioCfg.enDrv = GpioDrvL;		//端口驱动能力配置 						GPIO低驱动能力
    stcGpioCfg.enOD = GpioOdDisable;	//端口开漏配置							GPIO开漏输出关闭
    stcGpioCfg.enPd = GpioPdDisable;	//端口下拉配置 							GPIO无下拉
    Gpio_Init(GpioPortA, GpioPin3, &stcGpioCfg);
    Gpio_SetAfMode(GpioPortA, GpioPin3, GpioAf1);          //配置RX        
}

对于串口的中断我们需要注意,在初始化时,一定要先关闭串口发送中断使能。在后面需要时才打开。

2编写串口发送中断方式 发送数据 函数

static void Uart1_Config(void);
static void Uart1_PortInit(void);

#define U0_TX_MAX	500
uint8_t		U0_TX_BUF[U0_TX_MAX]={0};	//串口发送缓存区 
volatile	uint16_t	U0_TX_Cnt = 0;	
uint8_t		U0_TX_Index = 0;			//串口发送索引
volatile 	uint8_t U0_TX_BUSY = 0;

int32_t main(void)
{
    Uart1_Config();						//usrt1功能配置
	Uart1_PortInit();					//usrt1引脚配置

    UART1_SendStr("123");//测试
	UART1_SendStr("456");//测试 
	UART1_SendStr("789");//测试
    
    while(1)
    {
    }
}

void UART1_SendStr( unsigned char *str )
{

	if( U1_TX_BUSY == 0)  //串口发送空闲
	{
		U1_TX_Index = 0;	//串口发送起始索引为0
		U1_TX_BUSY = 1;		//串口1繁忙标志置 1
		U1_TX_Cnt = 0;        //清除缓存
	    memset(U1_TX_BUF, 0, sizeof(U1_TX_BUF));
		do
		{
			U1_TX_BUF[U1_TX_Cnt] = *(str + U1_TX_Cnt);  //数据放入到缓存
			U1_TX_Cnt++;
		} while(*(str+U1_TX_Cnt) != '\0');
		
		//开启串口发送中断
		Uart_EnableIrq(M0P_UART1,UartTxEIrq);    ///<使能串口1	Txe  发送缓存寄存器空 中断 
		Uart_DisableIrq(M0P_UART1,UartTxIrq);    ///<关闭串口1	Tx	 发送 中断 
		
        //这里注意当使能Txe而不是Tx时,不用先往发送缓存寄存器中放数据就能进入到串口1中断函数
		//M0P_UART1->SBUF_f.DATA = U1_TX_BUF[0];   //当BUF有数据时,TXE硬件置0表示BUF非空
	}
	else if( U1_TX_BUSY == 1)  //串口发送繁忙
	{
		while(1)    //死等待  直到串口1发送空闲
		{
			if( U1_TX_BUSY ==0)  
			{
				break;
			}
		}
		if( U1_TX_BUSY == 0)//串口1发送空闲
		{
			U1_TX_Index = 0;	//串口发送起始索引为0
			U1_TX_BUSY = 1;		//串口1繁忙标志置 1
			U1_TX_Cnt = 0;        //清除缓存
	        memset(U1_TX_BUF, 0, sizeof(U1_TX_BUF));
			do
			{
				U1_TX_BUF[U1_TX_Cnt] = *(str + U1_TX_Cnt);  //数据放入到缓存
				U1_TX_Cnt++;
			} while(*(str+U1_TX_Cnt) != '\0');
			
			//开启串口发送中断
			Uart_EnableIrq(M0P_UART1,UartTxEIrq);   ///<使能串口1 Txe 发送缓存寄存器空 中断 
			Uart_DisableIrq(M0P_UART1,UartTxIrq);   ///<关闭串口1 Tx	发送 中断 
		}
	}
}

void UART1_SendData( unsigned char *str ,uint16_t  count )
{
	if( U1_TX_BUSY == 0)  //串口发送空闲
	{
		U1_TX_Index = 0;	//串口发送索引为第2位
		U1_TX_BUSY = 1;		//串口1繁忙标志置 1
		U1_TX_Cnt = 0;        //清除缓存
	    memset(U1_TX_BUF, 0, sizeof(U1_TX_BUF));
		do
		{
			U1_TX_BUF[U1_TX_Cnt] = *(str + U1_TX_Cnt);  //数据放入到缓存
			U1_TX_Cnt++;
		} while(U1_TX_Cnt < count);
		
		//开启 串口发送寄存器空 中断
		Uart_EnableIrq(M0P_UART1,UartTxEIrq);    ///<使能串口1	Txe  中断 
		Uart_DisableIrq(M0P_UART1,UartTxIrq);    ///<使能串口1	Tx		发送中断 
	
		return ;
	}
	else if( U1_TX_BUSY == 1)  //串口发送繁忙
	{
		while(1)
		{
			if( U1_TX_BUSY ==0)
			{
				break;
			}
		}
		if( U1_TX_BUSY == 0)//串口发送空闲
		{
			U1_TX_Index = 0;	//串口发送索引为第2位
			U1_TX_BUSY = 1;		//串口1繁忙标志置 1
			U1_TX_Cnt = 0;        //清除缓存
	        memset(U1_TX_BUF, 0, sizeof(U1_TX_BUF));
			do
			{
				U1_TX_BUF[U1_TX_Cnt] = *(str + U1_TX_Cnt);  //数据放入到缓存
				U1_TX_Cnt++;
			} while(U1_TX_Cnt < count);
			
			//开启 串口发送寄存器空 中断
			Uart_EnableIrq(M0P_UART1,UartTxEIrq);    ///<使能串口1	Txe  中断 
			Uart_DisableIrq(M0P_UART1,UartTxIrq);    ///<使能串口1	Tx		发送中断 
		}
	}
	
}

void Uart1_IRQHandler(void)
{
	
	if(Uart_GetStatus(M0P_UART1, UartRC))        //UART1数据接收
    {
		Uart_ClrStatus(M0P_UART1, UartRC);       //清中断状态位
    } 
		

	//当ISR.TXE = 0 表示当前发送缓存满,	SBUF不能写入数据
	//当ISR.TXE = 1 表示当前发送缓存无数据,SBUF能写入数据
	//TXE == 1表示缓存空
	if(Uart_GetStatus(M0P_UART1, UartTxe) == 1)       
    {
		if( U1_TX_Index < U1_TX_Cnt)
		{
			M0P_UART1->SBUF_f.DATA = U1_TX_BUF[U1_TX_Index];    //发送数据
			U1_TX_Index++;
		
		}
		
    }
	
	if(Uart_GetStatus(M0P_UART1, UartTC) == 1) //TC =1表示发送完毕
	{
		
		if( U1_TX_Index == U1_TX_Cnt  ) //串口发送完最后一个字符 
		{
			U1_TX_BUSY =0;  //串口发送标志位置0 空闲
	
			Uart_DisableIrq(M0P_UART1,UartTxEIrq);         ///<关闭串口TC发送中断
		}
				
		
		
	}
}

这里的逻辑是当第一次发送数据(0x31,0x32,0x33)时,串口TX一定是空闲的,我们将串口置为繁忙,填充数据到串口缓存,之后开启串口发送缓存寄存器空 中断。一但开启(由于TXbuffer这时一定为空)直接进入  void Uart1_IRQHandler(void)

注意:关闭串口发送中断 不等于 无法判断标志位 ,或者说 关闭串口发送中断 不等于 标志位不会改变。(中断使能寄存器和标志位寄存器不是同一个)这是我们在Uart1_IRQHandler 去判断两个发送标志位的前提。

1进入if(Uart_GetStatus(M0P_UART1, UartTxe) == 1)  

判断if( U1_TX_Index < U1_TX_Cnt)

        满足,发送0x31

2进入if(Uart_GetStatus(M0P_UART1, UartTC) == 1)

判断if( U1_TX_Index == U1_TX_Cnt) 

        不满足,退出

3进入if(Uart_GetStatus(M0P_UART1, UartTxe) == 1)  

判断if( U1_TX_Index < U1_TX_Cnt)

        满足,发送0x32

4进入if(Uart_GetStatus(M0P_UART1, UartTC) == 1)

判断if( U1_TX_Index == U1_TX_Cnt) 

        不满足,退出

5进入if(Uart_GetStatus(M0P_UART1, UartTxe) == 1)  

判断if( U1_TX_Index < U1_TX_Cnt)

        满足,发送0x33

6进入if(Uart_GetStatus(M0P_UART1, UartTC) == 1)

判断if( U1_TX_Index == U1_TX_Cnt) 

        满足,U1_TX_BUSY 置0 ,关闭Txe串口发送寄存器空 中断

7.进入if(Uart_GetStatus(M0P_UART1, UartTxe) == 1)  

判断if( U1_TX_Index < U1_TX_Cnt)

        不满足,退出

8.退出Uart1_IRQHandler。至此UART1_SendStr("123");执行完毕

因篇幅问题不能全部显示,请点此查看更多更全内容

Top