driver/pt100.c

204 lines
7.7 KiB
C
Raw Permalink 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.

#include "pt100.h"
#pragma pack(1)
typedef struct
{
uint8_t address; // 从机地址
uint8_t code; // 功能码
uint16_t reg_address; // 寄存器地址
uint16_t reg_num; // 寄存器数量
uint16_t crc;
} pt100_data_t;
#pragma pack()
extern uart_t *uarts[UART_NUM_MAX];
static pt100_t handle;
float32 pt100_tempture[PT100_DATA_CHANNEL_NUM];
/* CRC low byte table */
static const unsigned char auchCRCLo[] =
{
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,
0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,
0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,
0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,
0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,
0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,
0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,
0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,
0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,
0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,
0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,
0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,
0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,
0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,
0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,
0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,
0x43, 0x83, 0x41, 0x81, 0x80, 0x40};
/* CRC high byte table */
static const unsigned char auchCRCHi[] =
{
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40};
/* Public functions ----------------------------------------------------------*/
/**
* @brief Calculate Modbus CRC16
* @param puchMsg: Data to calculate CRC
* @param usMsgLen: Data length
* @param puchCRCHi: High byte of CRC value
* @param puchCRCLo: Low byte of CRC value
* @note Send the low byte first
* @retval None
*/
void GetModbusCRC16(unsigned char *puchMsg, unsigned short usMsgLen,
unsigned char *puchCRCLo, unsigned char *puchCRCHi)
{
unsigned char uchCRCLo = 0xFF;
unsigned char uchCRCHi = 0xFF;
unsigned short uIndex = 0;
while (usMsgLen--)
{
uIndex = (unsigned char)(uchCRCHi ^ *puchMsg++);
uchCRCHi = (unsigned char)(uchCRCLo ^ auchCRCHi[uIndex]);
uchCRCLo = (unsigned char)(auchCRCLo[uIndex]);
}
*puchCRCLo = uchCRCHi;
*puchCRCHi = uchCRCLo;
}
static void pt100_rx_cb(uint8_t uart_index, uint8_t *data, uint16_t len)
{
uart_t *h = handle.huart;
if (h != NULL)
{
if (h->uart_index == uart_index)
{
if ((h->rx_sta & 0x8000) == 0) // 接收未完成
{
handle.ctx_recv_buf[h->rx_sta & 0X3FFF] = h->rxbuf[0];
h->rx_sta++;
if (h->rx_sta > (PT100_MODBUS_RECV_LENGTH - 1))
h->rx_sta = 0; // 接收数据错误,重新开始接收
}
}
}
}
static void pt100_uart_init(void)
{
if (uarts[PT100_RS485_PORT] == NULL)
{
uarts[PT100_RS485_PORT] = uart_create(USART4, FALSE, 1, pt100_rx_cb, FALSE, 0, NULL);
uarts[PT100_RS485_PORT]->uart_index = PT100_RS485_PORT;
}
}
void pt100_init(send_data_cb_t cb)
{
handle.send_data_cb = cb;
pt100_uart_init();
handle.huart = uarts[PT100_RS485_PORT];
DBG_ASSERT(handle.huart != NULL __DBG_LINE);
GPIO_RESET(RS485_EN2_GPIO_Port, RS485_EN2_Pin);
uart_recv_en(handle.huart);
handle.idel_flag = false;
osel_memset((uint8_t *)pt100_tempture, 0, sizeof(float32) * PT100_DATA_CHANNEL_NUM);
}
void pt100_process(void)
{
uart_t *h = handle.huart;
DBG_ASSERT(h != NULL __DBG_LINE);
pt100_data_t data;
data.address = 0x01;
data.code = 0x04;
data.reg_address = 0x0000;
data.reg_address = S2B_UINT16(data.reg_address);
data.reg_num = PT100_DATA_CHANNEL_NUM;
data.reg_num = S2B_UINT16(data.reg_num);
GetModbusCRC16((uint8_t *)&data, sizeof(pt100_data_t) - 2, (uint8_t *)&data.crc, (uint8_t *)&data.crc + 1);
h->rx_sta = 0;
handle.send_data_cb((uart_num_e)h->uart_index, (uint8_t *)&data, sizeof(pt100_data_t));
}
void pt100_data_deal(void)
{
uart_t *h = handle.huart;
uint8_t *p = handle.ctx_recv_buf;
uint8_t offset = 0;
uint16_t crc = 0, crc1 = 0;
uint16_t length = h->rx_sta;
uint16_t pt100_data[PT100_DATA_CHANNEL_NUM];
uint8_t pt100_data_length = 0;
if (h->rx_sta == 0)
{
return; // 未收到数据切换到下一个设备
}
h->rx_sta |= 0x8000; // 暂停串口接收数据20ms预留了充足的接收时间
if (p[offset] == 0x01 && p[++offset] == 0x04 && length > 4)
{
offset++;
// CRC校验
GetModbusCRC16(p, length - 2, (uint8_t *)&crc, (uint8_t *)&crc + 1);
osel_memcpy((uint8_t *)&crc1, p + length - 2, 2);
if (crc == crc1)
{
pt100_data_length = p[offset];
offset++; // 偏移过长度
osel_memcpy((uint8_t *)pt100_data, p + offset, pt100_data_length);
for (uint8_t i = 0; i < PT100_DATA_CHANNEL_NUM; i++)
{
pt100_data[i] = B2S_UINT16(pt100_data[i]);
if (pt100_data[i] != 0xffff)
{
pt100_tempture[i] = (float32)pt100_data[i] / 10;
}
else
{
pt100_tempture[i] = 129;
}
}
}
}
}