TT12-MCU/applications/RS_485.c
CSSC-WORK\murmur a436e04622 更新mem和malloc相关函数为rt_,确保内存使用对齐
修复TTIsReady 等函数bug, 解决TIMEOUT关闭无法关机的问题
屏蔽rtc更新的相关代码,避免死机
添加 RS_485.c,实现电量读取
cfg参数调整为5分钟关机,1分钟上报位置。测试ok,等待外场挂机测试。
2023-08-31 16:12:44 +08:00

234 lines
6.1 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 "RS232"
#define LOG_LVL LOG_LVL_INFO
#include <ulog.h>
#define TR485
#define SAMPLE_UART_NAME "uart6" /* 串口设备名称 */
static rt_timer_t timer485;
#ifndef MIN_FRAME_LEN
#define MIN_FRAME_LEN 10
#endif
/* 串口接收消息结构*/
struct rx_msg
{
rt_device_t dev;
rt_size_t size;
};
/* 串口设备句柄 */
static rt_device_t serial485;
/* 消息队列控制块 */
static struct rt_messagequeue rx485_mq;
//static char rx_buffer[RT_SERIAL_RB_BUFSZ/4 + 1];
/* 接收数据回调函数 */
static rt_err_t uart_input(rt_device_t dev, rt_size_t size)
{
struct rx_msg msg;
rt_err_t result;
static rt_size_t cachecnt=0;
cachecnt += size;
if (cachecnt < MIN_FRAME_LEN) {
LOG_W("not enough data, cached and waiting...");//处理半包
return -1;
}
msg.dev = dev;
msg.size = cachecnt;
result = rt_mq_send(&rx485_mq, &msg, sizeof(msg));
if ( result == -RT_EFULL)
{
/* 消息队列满 */
LOG_W("485 message queue full");
}
cachecnt = 0;
return result;
}
typedef struct{
uint8_t norVol[2];
uint8_t cnt[2];
uint8_t level[2];
uint8_t Ah[2];
uint8_t current[2];
uint8_t incu[2];
uint8_t temp1[2];
uint8_t temp2[2];
uint8_t temp3[2];
}BATT_INFO;
static BATT_INFO batt;
void sendCMD()
{
uint8_t cmd[] = { 0x01, 0x03, 0x00, 0x00, 0x00, 0x1d, 0x85, 0xc3 };
//send cmd
rt_pin_write(TR485_RE, PIN_HIGH);
rt_device_write(serial485, 0, cmd, sizeof(cmd));
rt_pin_write(TR485_RE, PIN_LOW);
}
void parseBattInfo(uint8_t *din, size_t len)
{
LOG_HEX("batt",16,din,len);
uint8_t head[]={0x01,0x03,0x3a};
if (rt_memcmp(din, head, sizeof(head)) != 0) {
LOG_W("answer from battery is error.");
}
rt_memcpy(&batt, din+sizeof(head), sizeof(batt));
LOG_D("batt=%X,%X,%d\%",batt.level[0],batt.level[1]);
}
/**
* 获取电池电量
* @return
*/
uint8_t getPowerLevel(void)
{
return batt.level[1];
}
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/4 + 1];
while (1)
{
rt_memset(&msg, 0, sizeof(msg));
/* 从消息队列中读取消息*/
result = rt_mq_recv(&rx485_mq, &msg, sizeof(msg), RT_WAITING_FOREVER);
if (result == RT_EOK)
{
/* 从串口读取数据*/
rx_length = rt_device_read(msg.dev, 0, rx_buffer, msg.size);
if (!rx_length) {
LOG_W("read from RS485 error");
continue;
}
LOG_I("%d Bytes received from RS485",rx_length);
LOG_HEX("485rx:",16,rx_buffer,rx_length);//print what received.
parseBattInfo(rx_buffer, rx_length);
}
}
}
static int uart485_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);
}
/* 查找串口设备 */
serial485 = rt_device_find(uart_name);
if (!serial485)
{
LOG_E("find %s failed!", uart_name);
return RT_ERROR;
}
/* 初始化消息队列 */
rt_mq_init(&rx485_mq, "rx485_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(serial485, RT_DEVICE_CTRL_CONFIG, &config);
#endif
/* 以 DMA 接收及轮询发送方式打开串口设备 */
rt_device_open(serial485, RT_DEVICE_FLAG_DMA_RX);
/* 设置接收回调函数 */
rt_device_set_rx_indicate(serial485, 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
/* 创建 serial 线程 */
rt_thread_t thread = rt_thread_create("RS485", serial_thread_entry, RT_NULL, 1024*2, 30-2, 10);
/* 创建成功则启动线程 */
if (thread != RT_NULL)
{
rt_thread_startup(thread);
}
else
{
ret = RT_ERROR;
}
timer485 = rt_timer_create("batt", sendCMD, RT_NULL, rt_tick_from_millisecond(10*1000), RT_TIMER_FLAG_PERIODIC);
/* 启动定时器1 */
if (timer485 != RT_NULL)
rt_timer_start(timer485);
return ret;
}
/* 导出到 msh 命令列表中 */
INIT_APP_EXPORT(uart485_dma_sample);