首页 > 其他分享 >基于GD32F407单片机与循环队列的BIT上报学习记录

基于GD32F407单片机与循环队列的BIT上报学习记录

时间:2023-03-06 17:34:32浏览次数:45  
标签:GD32F407 usart buf RS485 rx DRI 单片机 BIT data

c文件

static uint8_t rx_buf[MAX_485_RX_LEN] = {0};
static uint8_t rx_buf_data_cnt = DATA;
static uint8_t rs485TXBuf[MAX_485_RX_LEN] = {0};
usart_device_t usart_device_485 = {
	.rcv_state = DRI_RS485_STATE_IDLE,
	.front = 0,
	.rear = 0,
};

/*缓存区初始化*/
void dri_rs485_buf_empty(void)
{
	dri_usart_empty(&usart_device_485);
	memset(rx_buf, 0, sizeof(rx_buf));
	rx_buf_data_cnt = DATA;
}

/*中断接收,中断收一个数据,push一次*/
int dri_rs485_rcv(uint8_t data)
{
	int rv = 0;
	
	rv = dri_usart_plush(&usart_device_485, data);
	if(rv != 0)
	{
		printf("queue is full\r\n");
		dri_rs485_buf_empty();
	}
	return rv;
}

/*bit接收,循环一次,pop一个数据*/
int dri_rs485_buf_pop(uint8_t *data)
{
	int rv = 0;
	rv = dri_usart_pop(&usart_device_485, data);
	return rv;
}

/************************************************
函数名称 : dri_rs485_request_empty
功    能 : 当出现错误时,或者信息有误,如:slot不匹配,
			恢复初始状态
参    数 : 无
返 回 值 : 无
作    者 : 
*************************************************/
static void dri_rs485_request_empty(void)
{
	//memset(rx_buf, 0, sizeof(rx_buf));
	usart_device_485.rcv_state = DRI_RS485_STATE_IDLE;
	rx_buf_data_cnt = DRI_RS485_PKG_DATA;
}

/*
*********************************************************************************************************
*                                            dri_rs485_check_usart2()
*
* Description : Handle set packge
*
* Argument(s) : config : information at module.
* Return(s)   : none.
*
* Caller(s)   : app.c.
*
* Note(s)     : 包结构:0xaa 0x55 slot len type data... crc 0xfd 0xfd
********************************************************************************************************
*/
void dri_rs485_rcv_process(void)
{
	uint8_t data;
	int rv = 0;
	
	rv = dri_rs485_buf_pop(&data);
    if(rv != 0)
        return;
	
	switch(usart_device_485.rcv_state)
	{
		case STATE_IDLE: //head
			if(data == 0xaa)
			{
				usart_device_485.rcv_state = STATE_SYNC;
				rx_buf[DRI_RS485_PKG_IDLE] = data;
			}
			break;
		case STATE_SYNC:
			if(data == 0x55)
			{
				usart_device_485.rcv_state = STATE_SLOT;
				rx_buf[DRI_RS485_PKG_SYNC] = data;
			}
			else if(data == 0xaa)
			{
				usart_device_485.rcv_state = STATE_SYNC;
			}
			else
			{
				usart_device_485.rcv_state = STATE_IDLE;
			}
			break;
		case STATE_SLOT:
			rx_buf[DRI_RS485_PKG_SLOT] =  data;
			usart_device_485.rcv_state = STATE_LEN;
			break;
		case STATE_LEN:
			rx_buf[DRI_RS485_PKG_LEN] = data;
			usart_device_485.rcv_state = STATE_TYPE;
			break;	
		case STATE_TYPE:
			rx_buf[DRI_RS485_PKG_TYPE] = data;
			usart_device_485.rcv_state = STATE_TAIL;
			break;
		case STATE_TAIL:
			if(data == 0xfd)
			{
				usart_device_485.rcv_state = STATE_LAST;
			}
			else
			{
                /*在此等待报尾,在报尾到来之前的都是数据*/
				rx_buf[rx_buf_data_cnt++] = data; 
			}
			break;
		case STATE_LAST:
			if(data == 0xfd)
			{	
				usart_interrupt_disable(DRI_RS485_USART, USART_INT_RBNE);
				/* 
				数据写到了CRC位,由于是++后缀,rx_buf_data_cnt实际累加到了tail位,
				后面还有1B报尾,所以实际最后一个BYTE的索引为:rx_buf_data_cnt + 1;
				rx_buf_data_cnt计数从0开始,所以实际报长为rx_buf_data_cnt + 2。
				*/
				if(rx_buf[DRI_RS485_PKG_SLOT] != slot)
				{
					RS485_ERROR("slot error\r\n");
					goto pkg_error;
					
				}
				if (rx_buf[DRI_RS485_PKG_LEN] != rx_buf_data_cnt + 2)
				{
					RS485_ERROR("len error\r\n");
					goto pkg_error;
					
				}
				if (rx_buf[rx_buf_data_cnt -1] != checksum(rx_buf, rx_buf_data_cnt - 1))
				{
					RS485_ERROR("checksum error\r\n");
					goto pkg_error;
					
				}	    
				
				if(rx_buf[DRI_RS485_PKG_LEN] <= MAX_485_RX_LEN )
				{
					/*bit处理函数*/
					
				}
				dri_rs485_request_empty();
				usart_interrupt_enable(DRI_RS485_USART, USART_INT_RBNE);
			}
			else
			{
                /*数据中有可能有报尾结束符0xfd*/
				rx_buf[rx_buf_data_cnt++] = data;
				usart_device_485.rcv_state = STATE_TAIL;
				break;
			}
			return;
		default:
			break;
	}
	return;
	
	pkg_error:
		dri_rs485_request_empty();
		usart_interrupt_enable(DRI_RS485_USART, USART_INT_RBNE);
	
	return;
}

头文件

#if 0
#define RS485_DEBUG(format,...) printf(" LINE: %d: "format, __LINE__, ##__VA_ARGS__)
#else
#define RS485_DEBUG(format,...)
#endif

#if 1
#define RS485_ERROR(format,...) printf("FILE: "__FILE__" LINE: %d: "format"/n", __LINE__, ##__VA_ARGS__)
#else
#define RS485_ERROR(format,...)
#endif

#define DRI_PERIPH_USART        RCU_USART0
#define DRI_RS485_USART         USART0

#define DRI_RS485_EN_PIN        DRI_GPIOA_RS485_EN
#define DRI_RS485_EN_PORT       GPIOA
#define DRI_RS485_TX_PIN        DRI_GPIOA_RS485_TX
#define DRI_RS485_TX_PORT       GPIOA
#define DRI_RS485_RX_PIN        DRI_GPIOA_RS485_RX
#define DRI_RS485_RX_PORT       GPIOA

#define MAX_485_RX_LEN          160

/*****************************************state machine*****************************************/
#define STATE_IDLE 	         0x00 //0xaa
#define STATE_SYNC 	         0x01 //0x55
#define STATE_SLOT 	         0x02 //槽位号
#define STATE_LEN	         0x03 //报长
#define STATE_TYPE 	         0x04 //类型
#define STATE_TAIL 	         0x05 //0xfd
#define STATE_LAST 	         0x06 //0xfd

enum pkg_struct{
	DRI_RS485_PKG_IDLE,
	DRI_RS485_PKG_SYNC, 	         
	DRI_RS485_PKG_SLOT,
	DRI_RS485_PKG_LEN,
	DRI_RS485_PKG_TYPE,
	DRI_RS485_PKG_DATA,
	DRI_RS485_PKG_TAIL,
	DRI_RS485_PKG_LAST
};

 中断处理:

void USART0_IRQHandler(void)
{
	uint8_t data;
	
	if(usart_flag_get(USART0, USART_FLAG_PERR)!= RESET)
	{
		usart_data_receive(USART0);
		usart_flag_clear(USART0, USART_FLAG_PERR);
	}
	if(usart_flag_get(USART0, USART_FLAG_ORERR)!= RESET)
	{
		usart_data_receive(USART0);
		usart_flag_clear(USART0, USART_FLAG_ORERR);
	}
	if(usart_flag_get(USART0, USART_FLAG_FERR)!= RESET)
	{
		usart_data_receive(USART0);
		usart_flag_clear(USART0, USART_FLAG_FERR);
	}
	
    if(usart_interrupt_flag_get(USART0, USART_INT_FLAG_RBNE) !=RESET)
    {	
		usart_flag_clear(USART0, USART_FLAG_RBNE);

		data = usart_data_receive(USART0);
		dri_rs485_rcv(data);
	}
}

 上述方法与中断接收时将数据直接存入rx_buf,等待收完再处理的区别在于接收过程,其他没什么区别。

纯属记录学习,如有助益,不胜欢喜;如有问题,欢迎指正!

标签:GD32F407,usart,buf,RS485,rx,DRI,单片机,BIT,data
From: https://www.cnblogs.com/blog-xh/p/17184693.html

相关文章

  • GD32F407 timer延迟函数,非中断
    voiddri_timer_delay_init(dri_timer_calc_typetype){ timer_parameter_structptr_time; rcu_periph_clock_enable(PERIPH_DELAY_TIMER); rcu_timer_clock_presca......
  • GD32F407 ADC+DMA
    #defineVDDA_APPLI((uint32_t)3300)/*ValueofanalogvoltagesupplyVdda(unit:mV)*/#defineRANGE_12BITS((uint8......
  • opencv sharp MatToBitmapSource
    privateBitmapSourceMatToBitmapSource(Matmat,refbyte[]gray){PixelFormatpf=PixelFormats.Gray8;intrawStride......
  • Java位集合之BitMap,BitSet解析
    目录1Java位集合1.1Bit-Map1.1.1简介1.1.2添加1.1.3清除1.1.4查找1.2Bitmap应用1.2.1快速排序1.2.2快速去重1.2.3快速查找1.3BitSet1.4BloomFilters1.4.1简......
  • C++ 中的 bitset
    C++中的\(\textsf{bitset}\)是能够存储\(01\)的容器,这一点看似与布尔(bool)数组很像。而一个布尔类型将会占用\(1\)字节的空间,相对于\(\textsf{bitset}\)来讲\(1\)......
  • 51单片机实现呼吸灯和PWM
    1.实现呼吸灯,其实就是使用很多个for循环不断对P0端口进行设置#include<REGX52.H>sbitLED=P2^0;voidDelay(unsignedintt){while(t--);}voidmain(){unsignedcharT......
  • java——spring boot集成RabbitMQ——高级特效——死信代码示例
    首先,消息成为死信的条件:       首先看消息生产者,生产者和之前的一样,没什么变化(注意:后面统一把nomal改为normal了):          消费......
  • 新手学习单片机的首选到底是什么?
    一、首先为什么要先学51单片机?​因为51单片发展最早,应用最广泛,特别是I/O口的操作非常简单,而且相关的学习资料最多、教材最成熟,学习起来得心应手,入门很快。有了这个基础再去......
  • RabbitMQUtils
    自动创建消息队列和队列绑定关系importcom.lubansoft.center.process.task.api.constant.ProcessMQKeys;importcom.lubansoft.center.process.task.api.model.mq.Proc......
  • 计算机存储的最小单位是字节byte,不是位bit
     51单片机是8位的寄存器,汇编指令一次最小处理8位,也就是一个字节,不管是内存还是外存。内存、磁盘容量都是以多少字节为单位,没听说过多少个位的磁盘。磁盘的读写以字节......