GD32F103VE串口中断发送和接收

GD32F103VE串口中断发送和接收,本程序基于RS485完成测试,实现将收到的数据,再发送出去。

#include "USART1_Interrupt.h"
#include "stdio.h"  //getchar(),putchar(),scanf(),printf(),puts(),gets(),sprintf()
#include "string.h" //使能strcpy(),strlen(),memset()
#include "Timer0.h"
#include "delay.h"

uint8_t USART1_TX_Buffer[USART1_TX_Buffer_Size]; //USART1发送缓冲区数组;
uint8_t USART1_TX_Buffer_Send_Index=0;          //USART1_TX_Buffer[]的发送索引值;
uint8_t USART1_TX_Buffer_Load_Index=0;          //USART1_TX_Buffer[]的装载索引值
uint8_t USART1_TX_Completed_Flag;
uint8_t USART1_TX_Overtime_Conter;//USART1发送超时计数器

uint8_t USART1_RX_Buffer[USART1_RX_Buffer_Size]; //USART1接收缓冲区数组
uint8_t USART1_RX_Buffer_Load_Index;          //USART1_RX_Buffer[]的装载索引值
uint8_t USART1_RX_Time_Count;                 //USART1接收时间计数器
uint8_t USART1_RX_Completed_Flag;

void GD32F103_USART1_Init(unsigned int bound);
void RS485_RX_END(void);
void USART1_Load_Send_Data(void);

void RS485_Enable_Output_Init(void)
{
	rcu_periph_clock_enable(RCU_GPIOA);  //使能GPIOA时钟,enable GPIO clock 
	gpio_init(GPIOA, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_1);
	//将GPIOA1设置为输出上拉

	RS485_ENABLE_PIN_Output_High();
}

//函数功能:初始化串口1,这个和STM32F103VET6的USART2兼容
void GD32F103_USART1_Init(unsigned int bound)
{
	//NVIC_PRIGROUP_PRE4_SUB0:抢占优先级为4bit(取值为0~15),子优先级为0bit(没有响应优先级)
	//NVIC_PRIGROUP_PRE3_SUB1:抢占优先级为3bit(取值为0~7),子优先级为1bit(取值为0~1)
	//NVIC_PRIGROUP_PRE2_SUB2:抢占优先级为2bit(取值为0~3),子优先级为2bit(取值为0~3)
	//NVIC_PRIGROUP_PRE1_SUB3:抢占优先级为1bit(取值为0~1),子优先级为3bit(取值为0~7)
	//NVIC_PRIGROUP_PRE0_SUB4:抢占优先级为0bit(没有抢占优先级),子优先级为3bit(取值为0~15)
	nvic_priority_group_set(NVIC_PRIGROUP_PRE4_SUB0);//设置系统中断优先级"抢占优先级为4bit,子优先级为0bit"
	nvic_irq_enable(USART1_IRQn,0,0);
	//设置USART1_IRQn的中断优先级,抢占优先级为0,子优先级为0,USART interrupt configuration

串口初始化开始/
	rcu_periph_clock_enable(RCU_GPIOA);  //使能GPIOA时钟,enable GPIO clock 
	rcu_periph_clock_enable(RCU_USART1); //使能USART1时钟,enable USART clock

	gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_2);
	//将GPIOA2设置为AFIO口(复用IO口),输出上拉
	gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_3);
	//将GPIOA3设置为浮空输入口

	RS485_Enable_Output_Init();

	usart_deinit(USART1);                        //复位USART1,USART configure
	usart_baudrate_set(USART1,bound);          //设置USART1的波特率
	usart_word_length_set(USART1,USART_WL_8BIT); //设置USART1数据传输格式为8位
	usart_stop_bit_set(USART1,USART_STB_1BIT);   //设置USART1停止位为1位
	usart_parity_config(USART1,USART_PM_NONE);   //设置USART1无需奇偶校验
	usart_hardware_flow_rts_config(USART1,USART_RTS_DISABLE);  //设置不使能USART1的RTS引脚功能
	usart_hardware_flow_cts_config(USART1, USART_CTS_DISABLE); //设置不使能USART1的CTS引脚功能

	usart_receive_config(USART1, USART_RECEIVE_ENABLE);
	//根据USART_RECEIVE_ENABLE,设置串口控制寄存器USART_CTL0的串口接收使能
	usart_transmit_config(USART1, USART_TRANSMIT_ENABLE);
	//根据USART_TRANSMIT_ENABLE,设置串口控制寄存器USART_CTL0的串口发送使能
	usart_enable(USART1);//使能串口模块
串口初始化结束/

	usart_interrupt_enable(USART1, USART_INT_RBNE);
	//根据USART_INT_RBNE指定,使能串口接收寄存区为非空时产生中断
	//read data buffer not empty interrupt and overrun error interrupt
	//enable USART1 receive interrupt

/在串口中断服务函数中发送数据配置开始//
	usart_interrupt_disable(USART1, USART_INT_TBE);
	//根据USART_INT_TBE指定,不使能串口发送缓冲区为空中断
	//Disnables Transmit Data Register empty interrupt
	usart_interrupt_enable(USART1, USART_INT_TC);
	//根据USART_INT_TC指定,使能串口发送完成中断
	//transmission complete interrupt
/在串口中断服务函数中发送数据配置结束//

  Timer_Interrupt_Initializtion(TIMER0,1000,108);
	//当arr=500,psc=108时,则为1ms,误差为1us;
}

void RS485_RX_END(void)
{
	if(USART1_RX_Time_Count>0)
	{
		USART1_RX_Time_Count++;
		if(USART1_RX_Time_Count>3)
		{
			if( USART1_RX_Buffer[0]=='1' )//地址正确
			{
				USART1_RX_Completed_Flag = 1; //变频器响应正确
				USART1_TX_Completed_Flag = 0; //允许再次发送数据

				USART1_RX_Buffer[USART1_RX_Buffer_Load_Index]='\r';
				USART1_RX_Buffer[USART1_RX_Buffer_Load_Index+1]='\n';
				USART1_RX_Buffer[USART1_RX_Buffer_Load_Index+2]='\0';
				strcpy((char*)USART1_TX_Buffer,(char*)USART1_RX_Buffer);//将收到的数据发送出去
				USART1_Load_Send_Data();
			}
			else
			{
				USART1_RX_Completed_Flag = 2; //变频器响应错误,需要重新发送命令
				USART1_TX_Completed_Flag = 0; //允许再次发送数据
			}
	
			USART1_RX_Buffer_Load_Index = 0;
			USART1_RX_Time_Count = 0;
		}
	}
}
#ifndef __USART1_Interrupt_H
#define __USART1_Interrupt_H

#include "gd32f10x.h" //使能uint8_t,uint16_t,uint32_t,uint64_t,int8_t,int16_t,int32_t,int64_t

#define RS485_Enable_Output 		       PAout(1)
#define RS485_ENABLE_PIN_Output_High() GPIO_BOP(GPIOA)=GPIO_PIN_1  //定义RS485串口使能脚输出高电平
#define RS485_ENABLE_PIN_Output_Low()  GPIO_BC(GPIOA)=GPIO_PIN_1   //定义RS485串口使能脚输出低电平
#define RS485_ENABLE_PIN_Toggle() gpio_bit_write( GPIOA,GPIO_PIN_1,(bit_status)((1-gpio_input_bit_get(GPIOA,GPIO_PIN_1))) )
//GA1取反输出电平

#define USART1_TX_Buffer_Size 		      15
extern uint8_t USART1_TX_Buffer[USART1_TX_Buffer_Size];
extern uint8_t USART1_TX_Buffer_Send_Index;//USART1_TX_Buffer[]的发送索引值;
extern uint8_t USART1_TX_Buffer_Load_Index;//USART1_TX_Buffer[]的装载索引值
extern uint8_t USART1_TX_Completed_Flag;
extern uint8_t USART1_TX_Overtime_Conter;//USART1发送超时计数器

#define USART1_RX_Buffer_Size 		      125
extern  uint8_t USART1_RX_Buffer[USART1_RX_Buffer_Size]; //USART1接收缓冲区数组
extern uint8_t USART1_RX_Buffer_Load_Index;          //USART1_RX_Buffer[]的装载索引值
extern uint8_t USART1_RX_Time_Count;                 //USART1接收时间计数器
extern uint8_t USART1_RX_Completed_Flag;

extern void GD32F103_USART1_Init(unsigned int bound);
extern void RS485_RX_END(void);
extern void USART1_Load_Send_Data(void);

#endif
#include "Timer0.h"
#include "USART1_Interrupt.h"

void Timer_Interrupt_Initializtion(uint32_t timer_periph,uint16_t arr,uint16_t psc);

//函数功能:通用定时器0中断初始化
//这里时钟选择为APB1的2倍,而APB1为36M
//arr:自动重装值。
//psc:时钟预分频数
//Timer_Interrupt_Initializtion(TIMER0,50000,1080);//当arr=50000,psc=1080时,则为500ms,误差为10us;
//Timer_Interrupt_Initializtion(TIMER0,1000,108);//当arr=500,psc=108时,则为1ms,误差为1us;
//计算公式:arr*psc/108000000/1,当arr=250,psc=108时,则为0.25ms,误差为1us;
void Timer_Interrupt_Initializtion(uint32_t timer_periph,uint16_t arr,uint16_t psc)
{
	timer_parameter_struct TimerParameterStruct;

	switch(timer_periph)
	{
		case TIMER0:
    	rcu_periph_clock_enable(RCU_TIMER0);      //使能TIMER0的APB2外设时钟
		  nvic_irq_enable(TIMER0_UP_IRQn, 2U, 0U);  //设置TIMER0_UP_IRQn的中断优先级,抢占优先级为2,子优先级为0
    	break;
    case TIMER1:
			rcu_periph_clock_enable(RCU_TIMER1);
		  nvic_irq_enable(TIMER1_IRQn, 2U, 0U);  //设置TIMER1_IRQn的中断优先级,抢占优先级为2,子优先级为0
		  break;
    case TIMER2:
			rcu_periph_clock_enable(RCU_TIMER2);
		  nvic_irq_enable(TIMER2_IRQn, 2U, 0U);  //设置TIMER2_IRQn的中断优先级,抢占优先级为2,子优先级为0
		  break;
    case TIMER3:
			rcu_periph_clock_enable(RCU_TIMER3);
		  nvic_irq_enable(TIMER3_IRQn, 2U, 0U);  //设置TIMER3_IRQn的中断优先级,抢占优先级为2,子优先级为0
		  break;
    case TIMER4:
			rcu_periph_clock_enable(RCU_TIMER4);
		  nvic_irq_enable(TIMER4_IRQn, 2U, 0U);  //设置TIMER4_IRQn的中断优先级,抢占优先级为2,子优先级为0
		  break;
    case TIMER5:
			rcu_periph_clock_enable(RCU_TIMER5);
		  nvic_irq_enable(TIMER5_IRQn, 2U, 0U);  //设置TIMER5_IRQn的中断优先级,抢占优先级为2,子优先级为0
		  break;
    case TIMER6:
			rcu_periph_clock_enable(RCU_TIMER6);
		  nvic_irq_enable(TIMER6_IRQn, 2U, 0U);  //设置TIMER6_IRQn的中断优先级,抢占优先级为2,子优先级为0
		  break;
    default:
    	break;
	}
	timer_deinit(timer_periph);                 //复位TIMERx

TIMERx配置开始
	TimerParameterStruct.period            = arr-1; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
	TimerParameterStruct.prescaler         = psc-1; //设置用来作为TIMx时钟频率除数的预分频值(APB2时钟分频值)
	TimerParameterStruct.clockdivision     = TIMER_CKDIV_DIV1;   //设置时钟分母值为1
	//计算公式:arr*psc/108000000/1,当arr=250,psc=108时,则为0.25ms,误差为1us;
	TimerParameterStruct.counterdirection  = TIMER_COUNTER_UP;   //设置计数方向为"向上计数"
	TimerParameterStruct.alignedmode       = TIMER_COUNTER_EDGE; //设置为无中央对齐计数模式(边沿对齐模式)
	TimerParameterStruct.repetitioncounter = 0;                  //设置"重复计数次数"为0
	timer_init(timer_periph,&TimerParameterStruct);//根据TimerParameterStruct所指向的参数初始化TIMERx的时间基数单位
TIMERx配置结束

	timer_counter_value_config(timer_periph,0);//设置TIMERx的计数器初始值为0
	//timer_counter_read(timer_periph);//读取TIMERx的计数器值

  timer_auto_reload_shadow_enable(timer_periph);//使能TIMERx自动重装载

	timer_flag_clear(timer_periph,TIMER_FLAG_UP);               //清除"TIMERx更新标志位"
	timer_interrupt_flag_clear(timer_periph,TIMER_INT_FLAG_UP); //清除"TIMERx更新中断标志位"
	timer_interrupt_enable(timer_periph,TIMER_INT_UP);          //使能"TIMERx更新"产生中断

  timer_internal_clock_config(timer_periph);//设置"内部时钟"作为定时器时钟
	//timer_slave_mode_select(timer_periph,TIMER_SLAVE_MODE_DISABLE);
	//设置"关闭从模式",如果TIMER计数器使能,则预分频器直接由内部时钟驱动

	timer_enable(timer_periph);//TIMERx计数器使能,开始工作
}


//函数功能:TIMER0更新中断服务程序
void TIMER0_UP_IRQHandler(void)
{
	if( timer_interrupt_flag_get(TIMER0,TIMER_INT_FLAG_UP) )// 读取更新中断标志位
	{
		RS485_RX_END();//判断变频器接收是否完成
		timer_flag_clear(TIMER0,TIMER_FLAG_UP);               //清除"TIMER0更新标志位"
		timer_interrupt_flag_clear(TIMER0,TIMER_INT_FLAG_UP); //清除"更新中断标志位"
	}
}

main.c如下:

#include "gd32f10x.h" //使能uint8_t,uint16_t,uint32_t,uint64_t,int8_t,int16_t,int32_t,int64_t,bool
#include "stdio.h"  //getchar(),putchar(),scanf(),printf(),puts(),gets(),sprintf()
#include "string.h" //使能strcpy(),strlen(),memset()

#include "delay.h"
#include "USART1_Interrupt.h"

const char CPU_Reset_REG[]="\r\nCPU reset!\r\n";
int main(void)
{
	//NVIC_PRIGROUP_PRE4_SUB0:抢占优先级为4bit(取值为0~15),子优先级为0bit(没有响应优先级)
	//NVIC_PRIGROUP_PRE3_SUB1:抢占优先级为3bit(取值为0~7),子优先级为1bit(取值为0~1)
	//NVIC_PRIGROUP_PRE2_SUB2:抢占优先级为2bit(取值为0~3),子优先级为2bit(取值为0~3)
	//NVIC_PRIGROUP_PRE1_SUB3:抢占优先级为1bit(取值为0~1),子优先级为3bit(取值为0~7)
	//NVIC_PRIGROUP_PRE0_SUB4:抢占优先级为0bit(没有抢占优先级),子优先级为3bit(取值为0~15)
	nvic_priority_group_set(NVIC_PRIGROUP_PRE4_SUB0);//设置系统中断优先级"抢占优先级为4bit,子优先级为0bit"
  INTX_ENABLE();//开启所有中断
	delay_init();//初始化延迟函数

	GD32F103_USART1_Init(115200);
	strcpy((char*)USART1_TX_Buffer,CPU_Reset_REG);
	USART1_Load_Send_Data();

	while(1)
	{
	}
}

GD32F103VE串口中断发送和接收_第1张图片

 

你可能感兴趣的:(产品研发,单片机,嵌入式硬件,GD32,串口,RS485)