lpc5500的sdk中提供了非常丰富的串口例程(如下图所示):
但是,偏偏没有串口dma发送+中断接收这种组合。
实话说小编觉得这种组合才是大部分mcu场景中最常用的。尤其是对一些rx数据量不大(比如只是解析一些命令)但是tx数据量大的应用(比如定时,高频发送数据)再合适不过,该架构模型简单,非常容易理解。
本篇文章就手把手教大家分分钟撸一个dma发送+中断接收的例程:
我们复制一个dma_transfer例程作为模板,重命名为dma_tx_int_rx(名字无所谓,自己起即可)。打开,编译下载运行一下,确保原版demo在自己的板子上可以顺利的运行,咱们把前期工作都铺垫好。
下面我们开始改代码:dma_transfer原版代码是tx和rx都是dma传输,我们只需要将rx改为中断接收数据即可。
首先将usart_transfercreatehandledma函数修改下,将所有rx dma有关的东西去掉,handler填null就可以。这样usart_dmadriver就不会处理rx dma有关的操作了:
usart_transfercreatehandledma(demo_usart, &g_uartdmahandle, usart_usercallback, null,&g_uarttxdmahandle, null);
2. 开启usart rx中断,没啥可说的,常规操作:
/* enable rx interrupt. */ usart_enableinterrupts(demo_usart, kusart_rxlevelinterruptenable | kusart_rxerrorinterruptenable); enableirq(demo_usart_irqn);
3. 在app层定义(接管)串口硬件中断,并在中断中处理串口rx接收到的数据: #define demo_usart_irqhandler flexcomm0_irqhandler #define demo_usart_irqn flexcomm0_irqn
void demo_usart_irqhandler(void) { uint8_t data; /* if new data arrived. */ if ((kusart_rxfifonotemptyflag | kusart_rxerror | kusart_rxfifofullflag) & usart_getstatusflags(demo_usart)) { data = usart_readbyte(demo_usart); printf(usart rx interrupt:%c , data); if(data == 's')
{
/* send g_tipstring out. */
xfer.data = g_tipstring;
xfer.datasize = sizeof(g_tipstring) - 1;
g_uartdmahandle.txstate = kusart_txidle;
usart_transfersenddma(demo_usart, &g_uartdmahandle, &xfer);
}
}
if ((0u != (demo_usart->intenset & usart_intenset_txidleen_mask)) && (0u != (demo_usart->intstat & usart_intstat_txidle_mask)))
{
usart_transferdmahandleirq(demo_usart, &g_uartdmahandle);
}
}
注意,这里需要在硬件串口中断里判断txidle中断,并调用usart_transferdmahandleirq。这是仿照fsl_usart_dma.c中的写法(fsl_usart_dma中开启了txidle中断,并使用txidle中断来调用dma handle用户回调函数,现在硬件串口中断已经被app层接管,所以我们同样要实现这部分功能)。 4. 测试:改好代码,下载运行:当串口敲入任意键时候,程序都会回显接收到数据,当按键”s”时,会调用usart_transfersenddma函数使用dma发送一串数据,并进入dma发送完成回调函数。
代码清单
以下是完整代码清单(可以直接复制到usart_dma_transfer.c里运行):
/* * copyright (c) 2016, freescale semiconductor, inc.
* copyright 2016-2017 nxp
* all rights reserved.
*
* spdx-license-identifier: bsd-3-clause
*/
#include pin_mux.h
#include board.h
#include fsl_usart.h
#include fsl_usart_dma.h
#include fsl_dma.h
#include fsl_debug_console.h
#include
#include fsl_power.h
#define demo_usart usart0
#define demo_usart_clk_src kclock_flexcomm0
#define demo_usart_clk_freq clock_getflexcommclkfreq(0u)
#define usart_rx_dma_channel 4
#define usart_tx_dma_channel 5
#define example_uart_dma_baseaddr dma0
#define demo_usart_irqhandler flexcomm0_irqhandler
#define demo_usart_irqn flexcomm0_irqn
#define echo_buffer_length 8
usart_transfer_t xfer;
usart_dma_handle_t g_uartdmahandle;
dma_handle_t g_uarttxdmahandle;
uint8_t g_tipstring[] = this string is send from uart_dma ;
#define kusart_txidle 0
void usart_usercallback(usart_type *base, usart_dma_handle_t *handle, status_t status, void *userdata)
{
userdata = userdata;
if (kstatus_usart_txidle == status)
{
printf(usart_usercallback, status:0x%x , status);
}
}
void demo_usart_irqhandler(void) { uint8_t data; /* if new data arrived. */ if ((kusart_rxfifonotemptyflag | kusart_rxerror | kusart_rxfifofullflag) & usart_getstatusflags(demo_usart)) { data = usart_readbyte(demo_usart); printf(usart rx interrupt:%c , data); if(data == 's')
{
/* send g_tipstring out. */
xfer.data = g_tipstring;
xfer.datasize = sizeof(g_tipstring) - 1;
g_uartdmahandle.txstate = kusart_txidle;
usart_transfersenddma(demo_usart, &g_uartdmahandle, &xfer);
}
}
if ((0u != (demo_usart->intenset & usart_intenset_txidleen_mask)) && (0u != (demo_usart->intstat & usart_intstat_txidle_mask)))
{
usart_transferdmahandleirq(demo_usart, &g_uartdmahandle);
}
}
int main(void)
{
usart_config_t config;
/* set bod vbat level to 1.65v */
power_setbodvbatlevel(kpower_bodvbatlevel1650mv, kpower_bodhystlevel50mv, false);
/* attach 12 mhz clock to flexcomm0 (debug console) */
clock_attachclk(kfro12m_to_flexcomm0);
board_initbootpins();
board_initbootclocks();
board_initdebugconsole();
printf(usart: tx dma, rx interrupt );
printf(press 's' for dma tx tranmsit );
usart_getdefaultconfig(&config);
config.baudrate_bps = board_debug_uart_baudrate;
config.enabletx = true;
config.enablerx = true;
usart_init(demo_usart, &config, demo_usart_clk_freq);
/* configure dma. */
dma_init(example_uart_dma_baseaddr);
dma_enablechannel(example_uart_dma_baseaddr, usart_tx_dma_channel);
dma_enablechannel(example_uart_dma_baseaddr, usart_rx_dma_channel);
dma_createhandle(&g_uarttxdmahandle, example_uart_dma_baseaddr, usart_tx_dma_channel);
usart_transfercreatehandledma(demo_usart, &g_uartdmahandle, usart_usercallback, null, &g_uarttxdmahandle, null);
/* send g_tipstring out. */
xfer.data = g_tipstring;
xfer.datasize = sizeof(g_tipstring) - 1;
usart_transfersenddma(demo_usart, &g_uartdmahandle, &xfer);
/* enable rx interrupt. */
usart_enableinterrupts(demo_usart, kusart_rxlevelinterruptenable | kusart_rxerrorinterruptenable);
enableirq(demo_usart_irqn);
while (1);
}
变压器变比测试仪的作用_变压器变比测试仪的设计
戴姆勒通过架构重组计划 预计2020年完成
英飞凌携手SensiML为智能家居、健身和工业应用提供传感器数据并训练机器学习模型
投资400亿 国内首个柔性半导体服务基地“落地”西咸新区
UWB赛道快速崛起:推进技术发展,拓展落地应用
串口DMA发送+中断接收的例程
广电运通AI+安防,助力区域产业园区智慧升级
HTC U11怎么样?苹果iPhone7又迎来降价潮,面对年度旗舰HTC U11的强强压迫,你会怎么选?
SpaceX将继续开展 Q/V/Ka 等频段的通信性能测试
艾德克斯可为医疗电子设备提供专业的测试解决方案
水质检测实验室常规配置的仪器设备清单
dfrobotCheapduino控制器介绍
关于推导全差分放大器传递公式
汽车必备的5款小配件
船用主配电板和应急配电板的通电试验操作
再智能的驾驶,也离不开安全
铁路应用连接器
Altius探针卡的主要特征是什么
可穿戴式智能手机—努比亚α 即将量产,预计4月将在中国市场首销
浅析UWB技术在物联网中的应用价值