stm32f407,串口3DMA接收,现象:正常接收数据,数据有校验,数据长度是0xA6(不定长数据,这个是我数的)
接收到的数据是
发现进入两次中断,进入这个函数
static void uart_isr(struct rt_serial_device *serial)
{
struct stm32_uart *uart;
#ifdef RT_SERIAL_USING_DMA
rt_size_t recv_total_index, recv_len;
rt_base_t level;
#endif
RT_ASSERT(serial != RT_NULL);
uart = rt_container_of(serial, struct stm32_uart, serial);
/* UART in mode Receiver -------------------------------------------------*/
if ((__HAL_UART_GET_FLAG(&(uart->handle), UART_FLAG_RXNE) != RESET) &&
(__HAL_UART_GET_IT_SOURCE(&(uart->handle), UART_IT_RXNE) != RESET))
{
rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
}
#ifdef RT_SERIAL_USING_DMA
else if ((uart->uart_dma_flag) && (__HAL_UART_GET_FLAG(&(uart->handle), UART_FLAG_IDLE) != RESET)
&& (__HAL_UART_GET_IT_SOURCE(&(uart->handle), UART_IT_IDLE) != RESET))
{
level = rt_hw_interrupt_disable();
recv_total_index = serial->config.bufsz - __HAL_DMA_GET_COUNTER(&(uart->dma_rx.handle));
recv_len = recv_total_index - uart->dma_rx.last_index;
uart->dma_rx.last_index = recv_total_index;
rt_hw_interrupt_enable(level);
if (recv_len)
{
rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_DMADONE | (recv_len << 8));
}
__HAL_UART_CLEAR_IDLEFLAG(&uart->handle);
}
接收到的数据如下,上面是crc,下面是数量
F3 04 F7 F3 03 F6 F6 00 F6 F3 03 F6 F3 03 F6 A9 4D F6
26 80 A6 1C 8A A6 8D 19 A6 40 66 A6 40 66 A6 07 9F A6
相当于A6个数据,接收的时候按照两半接收的,原因是什么,怎么避免呢?
开启串口部分如下,dma缓冲区是6144,很大了:
struct serial_configure pconfig;
/* 初始化串口 */
if (dev == RT_NULL)
{
dev = rt_device_find(ENV_NAME);
RT_ASSERT(dev);
pconfig.baud_rate = BAUD_RATE_9600;
pconfig.data_bits = DATA_BITS_8;
pconfig.stop_bits = STOP_BITS_1;
pconfig.parity = PARITY_NONE;
pconfig.bit_order = BIT_ORDER_LSB;
pconfig.invert = NRZ_NORMAL;
pconfig.bufsz = 6144;
pconfig.reserved = 0;
/* 设置串口参数 */
rt_device_control(dev, RT_DEVICE_CTRL_CONFIG, &pconfig);
/*设置串口的回调函数 */
rt_device_set_rx_indicate(dev, env_recv_ind);
}
if(RT_EOK ==rt_device_open(dev, RT_DEVICE_FLAG_DMA_RX))
{
// rt_kprintf("Screen serial open success.\r\n");
// return RT_EOK;
}
else
{
// rt_kprintf("Screen serial open failure.\r\n");
// return RT_ERROR;
}
接收部分如下,USART3_RX_BUF是5000,也够大了。:
if ((rt_sem_take(&env_rx, 5000)) != RT_EOK)
{
continue;
}
recv_num = rt_device_read(dev,0,recv_str,5000);
memcpy(USART3_RX_BUF,recv_str,recv_num);
if (SEND_MODE == 1)
{
for(rt_uint8_t i=0;i<(recv_num-2);i++)
{
crc+=USART3_RX_BUF[i];
}
if((crc==USART3_RX_BUF[recv_num-1])&&(USART3_RX_BUF[0]>=1)&&(USART3_RX_BUF[0]<=24)&&(COMM_addr3==USART3_RX_BUF[0]))
{
if(USART3_RX_BUF[1]==0x03)
{
if(COMM_addr3!=USART3_RX_BUF[0])break;
if(USART3_RX_BUF[2]!=0x00)break;
if(USART3_RX_BUF[3]!=0xa0)break;
// addr=COMM_SN-1;
COMM_OK[COMM_addr3]=1;//这里是控制实时数据页面显示绿色 红色 灰色
for(rt_uint8_t i=0;i<160;i++)
{
SSSJ.uc[COMM_addr3][i]=USART3_RX_BUF[4+i];
}
realtime_data_recv = 1;
}
}
crc = 0;
}
多谢。在论坛里搜了一下,去掉了dma函数的注释,但是我的代码根本不会跑到那里,所以没用。
我只能用串口中断接收吗?