/* * 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 #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; }