G-CAMS-DATU/applications/Modbus/DATU.c

341 lines
10 KiB
C
Raw Normal View History

2024-05-16 11:07:30 +00:00
/*
* 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;
2024-05-17 07:00:05 +00:00
//CRC校验
2024-07-12 02:36:09 +00:00
static const rt_uint16_t CRC16_LIST[256] =
{
0x0000, 0x3096, 0x612C, 0x51BA, 0xC419, 0xF48F, 0xA535, 0x95A3,
0x8832, 0xB8A4, 0xE91E, 0xD988, 0x4C2B, 0x7CBD, 0x2D07, 0x1D91,
0x1064, 0x20F2, 0x7148, 0x41DE, 0xD47D, 0xE4EB, 0xB551, 0x85C7,
0x9856, 0xA8C0, 0xF97A, 0xC9EC, 0x5C4F, 0x6CD9, 0x3D63, 0x0DF5,
0x20C8, 0x105E, 0x41E4, 0x7172, 0xE4D1, 0xD447, 0x85FD, 0xB56B,
0xA8FA, 0x986C, 0xC9D6, 0xF940, 0x6CE3, 0x5C75, 0x0DCF, 0x3D59,
0x30AC, 0x003A, 0x5180, 0x6116, 0xF4B5, 0xC423, 0x9599, 0xA50F,
0xB89E, 0x8808, 0xD9B2, 0xE924, 0x7C87, 0x4C11, 0x1DAB, 0x2D3D,
0x4190, 0x7106, 0x20BC, 0x102A, 0x8589, 0xB51F, 0xE4A5, 0xD433,
0xC9A2, 0xF934, 0xA88E, 0x9818, 0x0DBB, 0x3D2D, 0x6C97, 0x5C01,
0x51F4, 0x6162, 0x30D8, 0x004E, 0x95ED, 0xA57B, 0xF4C1, 0xC457,
0xD9C6, 0xE950, 0xB8EA, 0x887C, 0x1DDF, 0x2D49, 0x7CF3, 0x4C65,
0x6158, 0x51CE, 0x0074, 0x30E2, 0xA541, 0x95D7, 0xC46D, 0xF4FB,
0xE96A, 0xD9FC, 0x8846, 0xB8D0, 0x2D73, 0x1DE5, 0x4C5F, 0x7CC9,
0x713C, 0x41AA, 0x1010, 0x2086, 0xB525, 0x85B3, 0xD409, 0xE49F,
0xF90E, 0xC998, 0x9822, 0xA8B4, 0x3D17, 0x0D81, 0x5C3B, 0x6CAD,
0x8320, 0xB3B6, 0xE20C, 0xD29A, 0x4739, 0x77AF, 0x2615, 0x1683,
0x0B12, 0x3B84, 0x6A3E, 0x5AA8, 0xCF0B, 0xFF9D, 0xAE27, 0x9EB1,
0x9344, 0xA3D2, 0xF268, 0xC2FE, 0x575D, 0x67CB, 0x3671, 0x06E7,
0x1B76, 0x2BE0, 0x7A5A, 0x4ACC, 0xDF6F, 0xEFF9, 0xBE43, 0x8ED5,
0xA3E8, 0x937E, 0xC2C4, 0xF252, 0x67F1, 0x5767, 0x06DD, 0x364B,
0x2BDA, 0x1B4C, 0x4AF6, 0x7A60, 0xEFC3, 0xDF55, 0x8EEF, 0xBE79,
0xB38C, 0x831A, 0xD2A0, 0xE236, 0x7795, 0x4703, 0x16B9, 0x262F,
0x3BBE, 0x0B28, 0x5A92, 0x6A04, 0xFFA7, 0xCF31, 0x9E8B, 0xAE1D,
0xC2B0, 0xF226, 0xA39C, 0x930A, 0x06A9, 0x363F, 0x6785, 0x5713,
0x4A82, 0x7A14, 0x2BAE, 0x1B38, 0x8E9B, 0xBE0D, 0xEFB7, 0xDF21,
0xD2D4, 0xE242, 0xB3F8, 0x836E, 0x16CD, 0x265B, 0x77E1, 0x4777,
0x5AE6, 0x6A70, 0x3BCA, 0x0B5C, 0x9EFF, 0xAE69, 0xFFD3, 0xCF45,
0xE278, 0xD2EE, 0x8354, 0xB3C2, 0x2661, 0x16F7, 0x474D, 0x77DB,
0x6A4A, 0x5ADC, 0x0B66, 0x3BF0, 0xAE53, 0x9EC5, 0xCF7F, 0xFFE9,
0xF21C, 0xC28A, 0x9330, 0xA3A6, 0x3605, 0x0693, 0x5729, 0x67BF,
0x7A2E, 0x4AB8, 0x1B02, 0x2B94, 0xBE37, 0x8EA1, 0xDF1B, 0xEF8D,
};
2024-05-16 11:07:30 +00:00
rt_uint16_t CRC16_Calculate(rt_uint8_t *data, rt_uint8_t len)
{
2024-07-12 02:36:09 +00:00
rt_uint16_t crcword = 0x0000;
2024-05-16 11:07:30 +00:00
2024-07-12 02:36:09 +00:00
for (rt_uint8_t i = 0; i < len; i++)
2024-05-16 11:07:30 +00:00
{
2024-07-12 02:36:09 +00:00
crcword = (crcword >> 8) ^ CRC16_LIST[((crcword ^ data[i]) & 0xFF)];
2024-05-16 11:07:30 +00:00
}
2024-07-12 02:36:09 +00:00
return crcword;
2024-05-16 11:07:30 +00:00
}
2024-07-12 02:36:09 +00:00
// 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);
2024-05-16 11:07:30 +00:00
2024-05-17 07:00:05 +00:00
//阅读命令
2024-05-16 11:07:30 +00:00
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];
2024-05-17 07:00:05 +00:00
rt_uint8_t send_buf[16] = { 'D', 'A', 'T', 'U' };
2024-05-16 11:07:30 +00:00
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
*
*/
2024-07-12 02:36:09 +00:00
rt_thread_mdelay(10);
2024-05-16 11:07:30 +00:00
2024-05-17 07:00:05 +00:00
// 主机命令或者有针数时发一条数据上去
if (DATU.send_data || get_IO_NeedleCountUpdateFlag()) {
rt_uint32_t temp = get_IO_NeedleCount_sum();
2024-07-12 02:36:09 +00:00
send_buf[7] = (temp >> 24) & 0xFF; // 获取最高8位
send_buf[6] = (temp >> 16) & 0xFF; // 获取次高8位
send_buf[5] = (temp >> 8) & 0xFF; // 获取次低8位
send_buf[4] = 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();
//直接发4096值
send_buf[9] = (get_ADC1_0_Value()>> 8) & 0xFF;
send_buf[8] = get_ADC1_0_Value() & 0xFF;
send_buf[11] = (get_ADC2_4_Value()>> 8) & 0xFF;
send_buf[10] = get_ADC2_4_Value() & 0xFF;
2024-05-17 07:00:05 +00:00
send_buf[13] = get_IO_Value(); //端口传感器状态
2024-05-16 11:07:30 +00:00
rt_uint16_t crc = CRC16_Calculate(send_buf + 4, 10);
// rt_kprintf("CRC %x\n ", crc);
2024-07-12 02:36:09 +00:00
send_buf[15] = crc >> 8;
send_buf[14] = crc & 0xFF;
2024-05-16 11:07:30 +00:00
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));
2024-05-17 07:00:05 +00:00
//接收主机发送的命令
2024-05-16 11:07:30 +00:00
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);
2024-05-17 07:00:05 +00:00
if (DATU.log)
{
rt_kprintf("CRC %x\n ", received_crc);
rt_kprintf("CRC %x\n ", calculated_crc);
}
//判断CRC是否一致
2024-05-16 11:07:30 +00:00
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;
}
2024-05-17 07:00:05 +00:00
//命令通过验证,读取命令细节
2024-05-16 11:07:30 +00:00
rc = read_cmd(read_buf, read_len);
2024-05-17 07:00:05 +00:00
if (rc == -1) //DATTU开头错误
2024-05-16 11:07:30 +00:00
{
if (DATU.log)
{
rt_kprintf("read header is not DATU.\n");
}
continue;
}
2024-05-17 07:00:05 +00:00
else if (rc == -2) //命令不是03和06
2024-05-16 11:07:30 +00:00
{
if (DATU.log)
{
rt_kprintf("read cmd is not 0x03 / 0x06.\n");
}
continue;
}
2024-05-17 07:00:05 +00:00
else if (rc == 3) //命令为03读取数据
2024-05-16 11:07:30 +00:00
{
if (DATU.log)
{
rt_kprintf("read cmd is 0x03.\n");
}
DATU.send_data =1;
continue;
}
2024-05-17 07:00:05 +00:00
else if (rc == 6) //06命令执行细节
2024-05-16 11:07:30 +00:00
{
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:
//主轴针数清零
2024-05-17 07:00:05 +00:00
set_IO_NeedleCount_sum(0);
2024-07-12 02:36:09 +00:00
DATU.send_data=1;
2024-05-16 11:07:30 +00:00
break;
case 2:
//闪灯
// IO_key(1, argv);
2024-05-17 07:00:05 +00:00
DATU.toggle_led = ~DATU.toggle_led;
2024-05-16 11:07:30 +00:00
break;
case 3:
//开锁1
2024-05-17 07:00:05 +00:00
rt_pin_write(OUT1, 0);
2024-05-16 11:07:30 +00:00
break;
case 4:
//开锁2
2024-05-17 07:00:05 +00:00
rt_pin_write(OUT2, 0);
2024-05-16 11:07:30 +00:00
break;
case 5:
//开锁3
2024-05-17 07:00:05 +00:00
rt_pin_write(OUT3, 0);
2024-05-16 11:07:30 +00:00
break;
case 6:
//报警灯开
2024-05-17 07:00:05 +00:00
rt_pin_write(OUT4, 0);
2024-05-16 11:07:30 +00:00
break;
case 7:
//报警灯关
2024-05-17 07:00:05 +00:00
rt_pin_write(OUT4, 1);
2024-05-16 11:07:30 +00:00
break;
default:
break;
}
}
}
}
void set_DATU_log(rt_uint8_t log)
{
DATU.log = log;
}
2024-05-17 07:00:05 +00:00
rt_uint8_t get_DATU_toggle_led()
{
return DATU.toggle_led;
}