基于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,等待收完再处理的区别在于接收过程,其他没什么区别。
纯属记录学习,如有助益,不胜欢喜;如有问题,欢迎指正!