G-CAMS-DATU/applications/Modbus/DATU.c
2024-05-17 15:00:05 +08:00

289 lines
7.3 KiB
C

/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2024-05-16 lijian the first version
*/
#include <DATU.h>
#define POLY 0x1021 // CRC-16-CCITT多项式
DATU_t DATU;
//CRC校验
rt_uint16_t CRC16_Calculate(rt_uint8_t *data, rt_uint8_t len)
{
rt_uint16_t CRC16in = 0xFFFF;
rt_uint16_t CPoly = 0xA001; /*0x8005高低位交换*/
while (len--)
{
CRC16in ^= *(data++);
for(rt_uint8_t i = 0;i < 8;i++)
{
if(CRC16in & 0x01)
CRC16in = (CRC16in >> 1) ^ CPoly;
else
CRC16in = CRC16in >> 1;
}
}
CRC16in = CRC16in % 256 * 256 + CRC16in / 256; /*调换高低Byte*/
return (CRC16in);
}
//阅读命令
rt_uint8_t read_cmd(rt_uint8_t read_buf[], rt_uint8_t read_len)
{
uint8_t correct_header[] = { 0x44, 0x41, 0x54, 0x55 };
if (memcmp(read_buf, correct_header, sizeof(correct_header)) == 0){
if (read_buf[4] == 0x03) {
return 3;
}
else if (read_buf[4] == 0x06){
return 6;
}
else{
return -2;
}
}
else{
return -1;
}
}
void datu_init()
{
rs485_inst_t *hinst = rs485_create(RS485_SAMPLE_MASTER_SERIAL, RS485_SAMPLE_MASTER_BAUDRATE,
RS485_SAMPLE_MASTER_PARITY, RS485_SAMPLE_MASTER_PIN, RS485_SAMPLE_MASTER_LVL);
if (hinst == RT_NULL)
{
rt_kprintf("create rs485 instance fail.\n");
return;
}
rs485_set_recv_tmo(hinst, 1000);
if (rs485_connect(hinst) != RT_EOK)
{
rs485_destory(hinst);
rt_kprintf("rs485 connect fail.\n");
return;
}
// rt_kprintf("Running.");
rt_int8_t send_len;
// rt_uint8_t send_buf[128];
rt_uint8_t send_buf[16] = { 'D', 'A', 'T', 'U' };
rt_uint8_t read_buf[10];
rt_int8_t read_len;
rt_uint8_t i;
rt_int8_t rc;
while (1)
{
/** 数据识别序列 数据内容 校验字
44 41 54 55 00 00 00 00 00 00 00 00 00 00 CRC
B0,B1,B2,B3 B4--B7 B8,B9 B10,B11 B12,B13 B14,B15
D, A, T, U 主轴针数 面线1张力值 面线2张力值 传感器状态 B4--B13的16位CRC
*
*/
rt_thread_mdelay(100);
// 主机命令或者有针数时发一条数据上去
if (DATU.send_data || get_IO_NeedleCountUpdateFlag()) {
rt_uint32_t temp = get_IO_NeedleCount_sum();
send_buf[4] = (temp >> 24) & 0xFF; // 获取最高8位
send_buf[5] = (temp >> 16) & 0xFF; // 获取次高8位
send_buf[6] = (temp >> 8) & 0xFF; // 获取次低8位
send_buf[7] = temp & 0xFF; // 获取最低8位
send_buf[8] = get_ADC1_0_H_ZL();
send_buf[9] = get_ADC1_0_L_ZL();
send_buf[10] = get_ADC2_4_H_ZL();
send_buf[11] = get_ADC2_4_L_ZL();
send_buf[13] = get_IO_Value(); //端口传感器状态
rt_uint16_t crc = CRC16_Calculate(send_buf + 4, 10);
// rt_kprintf("CRC %x\n ", crc);
send_buf[14] = crc >> 8;
send_buf[15] = crc & 0xFF;
send_len = rs485_send(hinst, (void *) send_buf, sizeof(send_buf));
DATU.send_data =0;
}
if (DATU.log)
{
rt_kprintf("rs485 send %d datas : ", send_len);
for (i = 0; i < send_len; i++)
{
rt_kprintf("%02X ", send_buf[i]);
}
rt_kprintf("\n");
send_len = 0;
}
// read_len = rs485_send_then_recv(hinst, (void *) send_buf, sizeof(send_buf), read_buf, sizeof(read_buf));
//接收主机发送的命令
read_len = rs485_recv(hinst, (void *) read_buf, sizeof(read_buf));
if (read_len < 0)
{
if (DATU.log)
{
rt_kprintf("rs485 read datas error.\n");
}
continue;
}
else if (read_len == 0)
{
if (DATU.log)
{
rt_kprintf("rs485 read timeout.\n");
}
continue;
}
//read_buf[read_len] = 0;
if (DATU.log)
{
rt_kprintf("rs485 read %d datas : ", read_len);
for (i = 0; i < read_len; i++)
{
rt_kprintf("%2X ", read_buf[i]);
}
rt_kprintf("\n");
}
//CRC校验
rt_uint16_t received_crc = (read_buf[7] << 8) | read_buf[8];
rt_uint16_t calculated_crc = CRC16_Calculate(read_buf+4, 3);
if (DATU.log)
{
rt_kprintf("CRC %x\n ", received_crc);
rt_kprintf("CRC %x\n ", calculated_crc);
}
//判断CRC是否一致
if (calculated_crc == received_crc) {
if (DATU.log)
{
rt_kprintf("read datas CRC OK\n");
}
} else {
if (DATU.log)
{
rt_kprintf("read datas CRC ERR\n");
}
continue;
}
//命令通过验证,读取命令细节
rc = read_cmd(read_buf, read_len);
if (rc == -1) //DATTU开头错误
{
if (DATU.log)
{
rt_kprintf("read header is not DATU.\n");
}
continue;
}
else if (rc == -2) //命令不是03和06
{
if (DATU.log)
{
rt_kprintf("read cmd is not 0x03 / 0x06.\n");
}
continue;
}
else if (rc == 3) //命令为03读取数据
{
if (DATU.log)
{
rt_kprintf("read cmd is 0x03.\n");
}
DATU.send_data =1;
continue;
}
else if (rc == 6) //06命令执行细节
{
if (DATU.log)
{
rt_kprintf("read cmd is 0x06.\n");
rt_kprintf("read cmd is %d .\n",read_buf[6]);
}
switch (read_buf[6]) {
case 1:
//主轴针数清零
set_IO_NeedleCount_sum(0);
break;
case 2:
//闪灯
// IO_key(1, argv);
DATU.toggle_led = ~DATU.toggle_led;
break;
case 3:
//开锁1
rt_pin_write(OUT1, 0);
break;
case 4:
//开锁2
rt_pin_write(OUT2, 0);
break;
case 5:
//开锁3
rt_pin_write(OUT3, 0);
break;
case 6:
//报警灯开
rt_pin_write(OUT4, 0);
break;
case 7:
//报警灯关
rt_pin_write(OUT4, 1);
break;
default:
break;
}
}
}
}
void set_DATU_log(rt_uint8_t log)
{
DATU.log = log;
}
rt_uint8_t get_DATU_toggle_led()
{
return DATU.toggle_led;
}