TT12-MCU/applications/uart_dma_sample.c
2023-07-04 12:02:15 +08:00

235 lines
6.6 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright (c) 2006-2022, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2019-04-16 misonyo first implementation.
*/
/*
* 程序清单:这是一个串口设备 DMA 接收使用例程
* 例程导出了 uart_dma_sample 命令到控制终端
* 命令调用格式uart_dma_sample uart3
* 命令解释:命令第二个参数是要使用的串口设备名称,为空则使用默认的串口设备
* 程序功能:通过串口输出字符串"hello RT-Thread!",并通过串口输出接收到的数据,然后打印接收到的数据。
*/
#include <rtthread.h>
#include <dfs_file.h>
#include <usrcfg.h>
#include <board.h>
#define LOG_TAG "uart"
#define LOG_LVL LOG_LVL_DBG
#include <ulog.h>
#ifdef WORK_BOARD
#define SAMPLE_UART_NAME "uart1" /* 串口设备名称 */
#else
#define SAMPLE_UART_NAME "uart3" /* 串口设备名称 */
#endif
#define MAX_SIZE_TO_SAVE 1024*2
/* 串口接收消息结构*/
struct rx_msg
{
rt_device_t dev;
rt_size_t size;
};
/* 串口设备句柄 */
static rt_device_t serial;
/* 消息队列控制块 */
static struct rt_messagequeue rx_mq;
/* 定时器的控制块 */
static rt_timer_t timer1;
/* 定时器1超时函数 */
static void timeout1(void *parameter)
{
// rt_kprintf("periodic timer is timeout %d\n", cnt);
// rt_timer_stop(timer1);
LOG_W("超时未收到新数据。");
}
/* 接收数据回调函数 */
static rt_err_t uart_input(rt_device_t dev, rt_size_t size)
{
struct rx_msg msg;
rt_err_t result;
msg.dev = dev;
msg.size = size;
result = rt_mq_send(&rx_mq, &msg, sizeof(msg));
if ( result == -RT_EFULL)
{
/* 消息队列满 */
rt_kprintf("message queue full\n");
}
return result;
}
struct rx_msg msg;
extern struct rt_event update_cfg;
extern int time2Str(char *str);
static void serial_thread_entry(void *parameter)
{
// struct rx_msg msg;
rt_err_t result;
rt_uint32_t rx_length=0;//单次收到的数据长度
static char rx_buffer[RT_SERIAL_RB_BUFSZ + 1];
static currLen=0;//已收数据长度
static char f[30];
time2Str(f);
while (1)
{
//暂定逻辑
//先创建文件
//接收数据并存盘
//
rt_memset(&msg, 0, sizeof(msg));
/* 从消息队列中读取消息*/
result = rt_mq_recv(&rx_mq, &msg, sizeof(msg), RT_WAITING_FOREVER);
if (result == RT_EOK)
{
/* 从串口读取数据*/
rx_length = rt_device_read(msg.dev, 0, rx_buffer, msg.size);
currLen += rx_length;
/* 启动定时器1 */
if (timer1 != RT_NULL)
rt_timer_start(timer1);
LOG_D("rec cnt=%d",rx_length);
LOG_HEX("rx:",16,rx_buffer,rx_length);//print what received.
#ifdef TR_ACK
/* 回传收到的消息 */
rt_device_write(serial, 0, rx_buffer+rx_length, rx_length);
#endif
if (0 && currLen > 1024) //大于1k则存盘
{
int fd =open(f,O_WRONLY | O_CREAT|O_APPEND);
if(fd <0)
{
LOG_E("open file %s failed!", f);
}
else
{
write(fd,rx_buffer,rx_length);
close(fd);
currLen = 0;
rx_length=0;
}
}
}
}
}
static int uart_dma_sample(int argc, char *argv[])
{
rt_err_t ret = RT_EOK;
char uart_name[RT_NAME_MAX];
static char msg_pool[256];
char str[] = {0x01,0x03,0x00,0x00,0x00,0x1d,0x85,0xc3};
if (argc == 2)
{
rt_strncpy(uart_name, argv[1], RT_NAME_MAX);
}
else
{
rt_strncpy(uart_name, SAMPLE_UART_NAME, RT_NAME_MAX);
}
/* 查找串口设备 */
serial = rt_device_find(uart_name);
if (!serial)
{
rt_kprintf("find %s failed!\n", uart_name);
return RT_ERROR;
}
/* 初始化消息队列 */
rt_mq_init(&rx_mq, "rx_mq",
msg_pool, /* 存放消息的缓冲区 */
sizeof(struct rx_msg), /* 一条消息的最大长度 */
sizeof(msg_pool), /* 存放消息的缓冲区大小 */
RT_IPC_FLAG_FIFO); /* 如果有多个线程等待,按照先来先得到的方法分配消息 */
#ifdef TR485
struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; /* 初 始 化 配 置 参 数 */
/* step2 修 改 串 口 配 置 参 数 */
config.baud_rate = BAUD_RATE_9600; //修 改 波 特 率 为 9600
config.data_bits = DATA_BITS_8; //数 据 位 8
config.stop_bits = STOP_BITS_1; //停 止 位 1
config.bufsz = 128; //修 改 缓 冲 区 buff size 为 128
config.parity = PARITY_NONE; //无 奇 偶 校 验 位
/* step3 控 制 串 口 设 备。 通 过 控 制 接 口 传 入 命 令 控 制 字, 与 控 制 参 数 */
rt_device_control(serial, RT_DEVICE_CTRL_CONFIG, &config);
#endif
/* 以 DMA 接收及轮询发送方式打开串口设备 */
rt_device_open(serial, RT_DEVICE_FLAG_DMA_RX);
/* 设置接收回调函数 */
rt_device_set_rx_indicate(serial, uart_input);
/* 发送字符串 */
#ifdef TR485
rt_pin_write(TR485_RE, PIN_HIGH);
rt_device_write(serial, 0, str, sizeof(str));
rt_pin_write(TR485_RE, PIN_LOW);
#endif
/* 创建定时器1 周期定时器 */
timer1 = rt_timer_create("rxtimer", timeout1,
RT_NULL, rt_tick_from_millisecond(40*1000),
RT_TIMER_FLAG_PERIODIC);
/* 创建 serial 线程 */
rt_thread_t thread = rt_thread_create("serial", serial_thread_entry, RT_NULL, 1024*2, 25+1, 10);
/* 创建成功则启动线程 */
if (thread != RT_NULL)
{
rt_thread_startup(thread);
}
else
{
ret = RT_ERROR;
}
return ret;
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(uart_dma_sample, uart device dma sample);
INIT_COMPONENT_EXPORT(uart_dma_sample);
void sendData(int argc, char *argv[])
{
//待发数据
char str[][50] =
{
{0x01,0x03,0x00,0x00,0x00,0x1d,0x85,0xc3},
"hello\r\n",
{0x5A,0xA5, 0x31, 0x32, 0x19, 0x06, 0x00, 0x01, 0x01, 0x1C, 0xED }
};
size_t size[]={8,strlen(str[1]),11};//对应每一维数据长度
size_t index = 0;
if (argc == 2) {
index = atoi(argv[1]);
}
size_t rst = rt_device_write(serial, 0, str[index], size[index]);
LOG_D("send %d Bytes ok.",rst);
}
MSH_CMD_EXPORT(sendData,3)