2224|0

23

帖子

0

TA的资源

一粒金砂(中级)

楼主
 

【雅特力AT-START-F435】USART发送、VOFA+上位机使用、串口空闲中断+DMA不定长接收 [复制链接]

 
 

本次测评中参考例程中USART,实现多通道采样及上位机波形显示。

参考文件目录如下:

AT32F435_437_Firmware_Library_V2.1.2\project\at_start_f435\examples\usart\transfer_by_dma_interrupt

USART的使用

功能简介

AT32F435/437有4个同步异步收发器(USART)、4个异步收发器(UART),支持IrDA SIR ENDEC传输编解码、多处理器通信模式、单线半双工通信模式和LIN主/从功能,其中串口1、2、3、6支持硬件的CTS和RTS信号管理、兼容ISO7816的智能卡模式和类似SPI通信模式。8个串口波特率高达9Mbit/s,且都可以使用DMA。

串口发送

使用轮询发送,官方提供的API中,下面的函数只能发送单个字节。

void usart_data_transmit(usart_type* usart_x, uint16_t data)

{

usart_x->dt = (data & 0x01FF);

}

下面是自己写的串口发送数组函数,发送单个字节后需要判断发送完成标志USART_TDC_FLAG,才能发送下一个函数

void usart_buf_trans(uint8_t* data_buf,uint32_t data_size)

{

//轮询发送

uint32_t i = 0;

for ( i = 0; i < data_size; i++)

{

usart_data_transmit(USART2,data_buf[i]);

while (RESET == usart_flag_get(USART2, USART_TDC_FLAG)) ;

}

}

使用VOFA打印float类型的数据

协议的参考文档为https://www.vofa.plus/

void USART_VOFA_JUSTFLOAT_FLOATBUF_TRANS(float *data, uint16_t data_size)

{

uint16_t var = 0;

uint8_t data_tmp[4] = { 0 };

uint8_t tail[4] = { 0x00, 0x00, 0x80, 0x7f };

for (var = 0; var < data_size; var++)

{

memcpy(data_tmp, (uint8_t *)&data[var], sizeof(data[var]));

usart_buf_trans(data_tmp,4);

}

usart_buf_trans(tail, 4);

}

效果如下:

串口空闲中断+DMA接收

串口接收一般有三种方式:(1)轮询接收;(2)中断接收;(3)串口空闲中断+DMA不定长接收。

第一种方式需要单片机不断循环读取串口的状态,如果读取的频率不够高,可能后漏掉一部分信息;第二种方式一般是定长接收,在发送、接收双方约定好数据帧的格式和长度的情况下较为使用;第三种方式一般是用于接收不定长的数据。方式1和方式2较为简单,下面记录一下串口空闲中断+DMA接收接收不定长数据。

GPIO初始化

使用串口2做发送和接收,可以从数据手册中可以找到,IO和串口的对应关系是,PA2->USART2_TX,PA3->USART2_RX。Gpio的muxing function应该选择GPIO_MUX_7。

参考代码如下:

gpio_default_para_init(&gpio_init_struct);

/* configure the usart2 tx, rx pin */

gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;

gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;

gpio_init_struct.gpio_mode = GPIO_MODE_MUX;

gpio_init_struct.gpio_pins = GPIO_PINS_2 | GPIO_PINS_3;

gpio_init_struct.gpio_pull = GPIO_PULL_NONE;

gpio_init(GPIOA, &gpio_init_struct);

gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE2, GPIO_MUX_7);

gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE3, GPIO_MUX_7);

USART初始化

选择串口2,波特率选择115200(USB转TTL模块不支持单片机的最高9M波特率),8位数据,1位停止位,同时使能串口的接收和发送,使能串口的DMA接收和发送。打开串口的空闲中断。

/* configure usart2 param */

usart_init(USART2, 115200, USART_DATA_8BITS, USART_STOP_1_BIT);

usart_transmitter_enable(USART2, TRUE);

usart_receiver_enable(USART2, TRUE);

usart_dma_transmitter_enable(USART2, TRUE);

usart_dma_receiver_enable(USART2, TRUE);

usart_enable(USART2, TRUE);



//enable usart2 IDLE interrupt

usart_interrupt_enable(USART2,USART_IDLE_INT,TRUE);

nvic_irq_enable(USART2_IRQn, 1, 1);

DMA初始化

我们可以从图中看出USART2的DMA请求来源是26和27,使用了DMA1.首先打开DMA1,初始化DMA,方向是从外设地址到内存,还有其余的一些初始化项(和STM32一样的,不再赘述)。最后打开DMA的接收完成中断。

dmamux_enable(DMA1, TRUE);

/* dma1 channel2 for usart2 rx configuration */

dma_reset(DMA1_CHANNEL2);

dma_default_para_init(&dma_init_struct);

dma_init_struct.buffer_size = USART2_RX_BUFFER_SIZE;

dma_init_struct.direction = DMA_DIR_PERIPHERAL_TO_MEMORY;

dma_init_struct.memory_base_addr = (uint32_t)usart2_rx_buffer;

dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_BYTE;

dma_init_struct.memory_inc_enable = TRUE;

dma_init_struct.peripheral_base_addr = (uint32_t)&USART2->dt;

dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_BYTE;

dma_init_struct.peripheral_inc_enable = FALSE;

dma_init_struct.priority = DMA_PRIORITY_MEDIUM;

dma_init_struct.loop_mode_enable = FALSE;

dma_init(DMA1_CHANNEL2, &dma_init_struct);

/* enable transfer full data intterrupt */

dma_interrupt_enable(DMA1_CHANNEL2, DMA_FDT_INT, TRUE);

/* dma1 channel2 interrupt nvic init */

nvic_irq_enable(DMA1_Channel2_IRQn, 0, 0);

/* config flexible dma for usart2 rx */

dmamux_init(DMA1MUX_CHANNEL2, DMAMUX_DMAREQ_ID_USART2_RX);



/* usart2 tx begin dma transmitting */

dma_channel_enable(DMA1_CHANNEL1, TRUE);

/* usart2 rx begin dma receiving */

dma_channel_enable(DMA1_CHANNEL2, TRUE);

中断服务函数

DMA可以直接把USART的数据搬运到指定内存的位置,但如何获取传输数据量的大小呢,可以通过下面的逻辑来实现

在at32f435_f437_int.c文件中找到串口空闲中断的服务函数,添加自己的用户函数,过程如下:①判断中断来源是串口空闲中断;②关闭DMA,防止修改DMA时DMA传输失败;③USART2_RX_BUFFER_SIZE是DMA传输的最大数量,dma_data_number_get(DMA1_CHANNEL2)可以获取DMA传输完成后、串口空闲中断发生时,DMA通道未传输的数据的个数,相减就可以计算出本次传输数据的个数;④重新打开DMA,并把DMA传输数据的个数重新设置为USART2_RX_BUFFER_SIZE。

/**

* [url=home.php?mod=space&uid=159083]@brief[/url] this function handles usart2 handler.

* @param none

* @retval none

*/

void USART2_IRQHandler(void)

{

if (SET == usart_flag_get(USART2, USART_IDLEF_FLAG))

{

usart_flag_clear(USART2, USART_IDLEF_FLAG);

dma_channel_enable(DMA1_CHANNEL2, FALSE);

usart_recv_status.recv_data_size = USART2_RX_BUFFER_SIZE - dma_data_number_get(DMA1_CHANNEL2);

usart_recv_status.recv_end_flag = SET;



usart_recv_data_proc();

//data process



//reopen the usart2_rx_dma_channel

dma_data_number_set(DMA1_CHANNEL2, USART2_RX_BUFFER_SIZE);

dma_channel_enable(DMA1_CHANNEL2, TRUE);

usart_recv_status_reset(&usart_recv_status);

}

}

 

点赞 关注
 
 

回复
举报
您需要登录后才可以回帖 登录 | 注册

查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/8 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表