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

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,等待收完再处理的区别在于接收过程,其他没什么区别。

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

posted @ 2023-03-06 17:23  xMofang  阅读(72)  评论(0编辑  收藏  举报