[feat] add read function

This commit is contained in:
zhji 2024-06-01 16:18:56 +08:00
parent aed3224ddc
commit 4982262f6d
3 changed files with 505 additions and 9 deletions

330
lark1s/lark1s.c Normal file
View File

@ -0,0 +1,330 @@
#include "lark1s.h"
/* information register */
#define LARK1S_REG_SN (0x0004)
#define LARK1S_SIZE_SN (8)
#define LARK1S_REG_GAS3_INFO (0x0300)
#define LARK1S_SIZE_GAS3_INFO (42)
#define LARK1S_REG_GAS3_CALI_DATA (0x032A)
#define LARK1S_SIZE_GAS3_CALI_DATA (24)
/* data register */
#define LARK1S_REG_DATA (0x0500)
#define LARK1S_SIZE_DATA (52)
/* writable register */
#define LARK1S_REG_GAS3_CALI_ZERO_RECORD (0x1012)
#define LARK1S_SIZE_GAS3_CALI_ZERO_RECORD (1)
#define LARK1S_REG_GAS3_CALI_SPAN_RECORD (0x1028)
#define LARK1S_SIZE_GAS3_CALI_SPAN_RECORD (1)
#define LARK1S_REG_GAS3_CALI_ACTIVE (0x103E)
#define LARK1S_SIZE_GAS3_CALI_ACTIVE (1)
#define LARK1S_REG_GAS3_CALI_RESTORE (0x1042)
#define LARK1S_SIZE_GAS3_CALI_RESTORE (1)
/* status register */
#define LARK1S_REG_STATUS (0x0600)
#define LARK1S_SIZE_STATUS (11)
#define MODBUS_FUNCTION_CODE_READ_INPUT (0x04)
#define MODBUS_FUNCTION_CODE_WRITE_SINGLE (0x06)
#define MODBUS_FUNCTION_CODE_WRITE_MULTI (0x10)
#define MB_GET_HWORD(p) (uint16_t)((((uint8_t*)p)[0] << 8) | ((uint8_t*)p)[1])
#define MB_GET_UWORD(p) (uint32_t)((((uint8_t*)p)[0] << 24) | (((uint8_t*)p)[1] << 16) | (((uint8_t*)p)[2] << 8) | ((uint8_t*)p)[3])
#define MB_GET_SWORD(p) (int32_t)((((uint8_t*)p)[0] << 24) | (((uint8_t*)p)[1] << 16) | (((uint8_t*)p)[2] << 8) | ((uint8_t*)p)[3])
static volatile uint8_t mb_addr = 0x01;
static volatile uint16_t mb_errno = 0x00;
struct crc16_result_s {
uint8_t crch;
uint8_t crcl;
};
static const uint8_t crc_tabl[] = { //CRC low Value Table
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,
};
static const uint8_t crc_tabh[] = { //CRC high Value Table
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,
};
/* polynomial: x16+x15+x2+x1 */
static void crc16_8005_calc(uint8_t *p, uint16_t len, struct crc16_result_s *ret)
{
struct crc16_result_s crc = {0xFF, 0xFF};
uint8_t i, index;
for (i = 0; i < len; i++) {
index = crc.crcl ^ p[i];
crc.crcl = crc.crch ^ crc_tabl[index];
crc.crch = crc_tabh[index];
}
ret->crcl = crc.crcl;
ret->crch = crc.crch;
}
static int lark1s_frame_check(uint8_t *p, uint16_t len)
{
struct crc16_result_s crc;
if (len < 5) {
return LARK1S_PARSE_FRAME_ERROR;
}
if (p[0] != mb_addr) {
return LARK1S_PARSE_MB_ADDR_NOT_MATCH;
}
crc16_8005_calc(p, len - 2, &crc);
if (crc.crcl != p[len - 2] || crc.crch != p[len - 1]) {
return LARK1S_PARSE_CRC_ERROR;
}
return LARK1S_PARSE_OK;
}
void lark1s_set_mb_address(uint8_t address)
{
mb_addr = address;
}
uint16_t lark1s_get_mb_errno(void)
{
return mb_errno;
}
int lark1s_req_sn(uint8_t *buffer)
{
struct crc16_result_s crc;
int i = 0;
buffer[i++] = mb_addr;
buffer[i++] = MODBUS_FUNCTION_CODE_READ_INPUT;
buffer[i++] = (LARK1S_REG_SN >> 8) & 0xFF;
buffer[i++] = LARK1S_REG_SN & 0xFF;
buffer[i++] = (LARK1S_SIZE_SN >> 8) & 0xFF;
buffer[i++] = LARK1S_SIZE_SN & 0xFF;
crc16_8005_calc(buffer, i, &crc);
buffer[i++] = crc.crcl;
buffer[i++] = crc.crch;
return i;
}
int lark1s_parse_sn(uint8_t *buffer, int length, char *sn)
{
int ret;
int i = 0;
ret = lark1s_frame_check(buffer, length);
if (ret) {
return ret;
}
i++;
if (buffer[i++] != MODBUS_FUNCTION_CODE_READ_INPUT) {
return LARK1S_PARSE_FUNCTION_CODE_ERROR;
}
if (buffer[i++] != LARK1S_SIZE_SN * 2) {
return LARK1S_PARSE_DATA_LENGTH_ERROR;
}
for (int j = 0; j < LARK1S_SIZE_SN * 2; j++) {
sn[j] = buffer[i++];
}
return LARK1S_PARSE_OK;
}
int lark1s_req_gas3_info(uint8_t *buffer)
{
struct crc16_result_s crc;
int i = 0;
buffer[i++] = mb_addr;
buffer[i++] = MODBUS_FUNCTION_CODE_READ_INPUT;
buffer[i++] = (LARK1S_REG_GAS3_INFO >> 8) & 0xFF;
buffer[i++] = LARK1S_REG_GAS3_INFO & 0xFF;
buffer[i++] = (LARK1S_SIZE_GAS3_INFO >> 8) & 0xFF;
buffer[i++] = LARK1S_SIZE_GAS3_INFO & 0xFF;
crc16_8005_calc(buffer, i, &crc);
buffer[i++] = crc.crcl;
buffer[i++] = crc.crch;
return i;
}
int lark1s_parse_gas3_info(uint8_t *buffer, int length, struct lark1s_gas_info_s *info)
{
int ret;
int i = 0;
ret = lark1s_frame_check(buffer, length);
if (ret) {
return ret;
}
i++;
if (buffer[i++] != MODBUS_FUNCTION_CODE_READ_INPUT) {
return LARK1S_PARSE_FUNCTION_CODE_ERROR;
}
if (buffer[i++] != LARK1S_SIZE_GAS3_INFO * 2) {
return LARK1S_PARSE_DATA_LENGTH_ERROR;
}
info->gas_id = MB_GET_UWORD(buffer + i);
for (int j = 0; j < 12; j++) {
info->gas_name[j] = buffer[i + 4 + j];
}
info->unit_id = MB_GET_UWORD(buffer + i + 16);
for (int j = 0; j < 8; j++) {
info->unit_name[j] = buffer[i + 20 + j];
}
info->range = MB_GET_UWORD(buffer + i + 32);
info->min_cali = MB_GET_UWORD(buffer + i + 56);
return LARK1S_PARSE_OK;
}
int lark1s_req_data(uint8_t *buffer)
{
struct crc16_result_s crc;
int i = 0;
buffer[i++] = mb_addr;
buffer[i++] = MODBUS_FUNCTION_CODE_READ_INPUT;
buffer[i++] = (LARK1S_REG_DATA >> 8) & 0xFF;
buffer[i++] = LARK1S_REG_DATA & 0xFF;
buffer[i++] = (LARK1S_SIZE_DATA >> 8) & 0xFF;
buffer[i++] = LARK1S_SIZE_DATA & 0xFF;
crc16_8005_calc(buffer, i, &crc);
buffer[i++] = crc.crcl;
buffer[i++] = crc.crch;
return i;
}
int lark1s_parse_data(uint8_t *buffer, int length, struct lark1s_data_s *data)
{
int ret;
int i = 0;
ret = lark1s_frame_check(buffer, length);
if (ret) {
return ret;
}
i++;
if (buffer[i++] != MODBUS_FUNCTION_CODE_READ_INPUT) {
return LARK1S_PARSE_FUNCTION_CODE_ERROR;
}
if (buffer[i++] != LARK1S_SIZE_DATA * 2) {
return LARK1S_PARSE_DATA_LENGTH_ERROR;
}
data->det_temp = MB_GET_UWORD(buffer + i);
data->air_pressure = MB_GET_UWORD(buffer + i + 8);
data->cts_ref = MB_GET_UWORD(buffer + i + 36);
data->gas3_reading = MB_GET_UWORD(buffer + i + 64);
data->cts_gas3 = MB_GET_UWORD(buffer + i + 68);
data->gas3_compensated_reading = MB_GET_SWORD(buffer + i + 104);
return LARK1S_PARSE_OK;
}
int lark1s_req_gas3_cali_zero_record(uint8_t *buffer);
int lark1s_parse_gas3_cali_zero_record(uint8_t *buffer, int length)
{
int ret;
ret = lark1s_frame_check(buffer, length);
if (ret) {
return ret;
}
return LARK1S_PARSE_OK;
}
int lark1s_req_gas3_cali_span_record(uint8_t *buffer, uint32_t concentration);
int lark1s_parse_gas3_cali_span_record(uint8_t *buffer, int length)
{
int ret;
ret = lark1s_frame_check(buffer, length);
if (ret) {
return ret;
}
return LARK1S_PARSE_OK;
}
int lark1s_req_gas3_cali_active(uint8_t *buffer);
int lark1s_parse_gas3_cali_active(uint8_t *buffer, int length)
{
int ret;
ret = lark1s_frame_check(buffer, length);
if (ret) {
return ret;
}
return LARK1S_PARSE_OK;
}
int lark1s_req_gas3_cali_restore(uint8_t *buffer);
int lark1s_parse_gas3_cali_restore(uint8_t *buffer, int length)
{
int ret;
ret = lark1s_frame_check(buffer, length);
if (ret) {
return ret;
}
return LARK1S_PARSE_OK;
}
int lark1s_req_status(uint8_t *buffer);
int lark1s_parse_status(uint8_t *buffer, int length, struct lark1s_status_s *status)
{
int ret;
ret = lark1s_frame_check(buffer, length);
if (ret) {
return ret;
}
return LARK1S_PARSE_OK;
}

78
lark1s/lark1s.h Normal file
View File

@ -0,0 +1,78 @@
#ifndef __LARK1S_H__
#define __LARK1S_H__
#include "stdint.h"
#define LARK1S_PARSE_OK (0)
#define LARK1S_PARSE_MB_ADDR_NOT_MATCH (1)
#define LARK1S_PARSE_FUNCTION_CODE_ERROR (2)
#define LARK1S_PARSE_FRAME_ERROR (3)
#define LARK1S_PARSE_CRC_ERROR (4)
#define LARK1S_PARSE_DATA_LENGTH_ERROR (5)
struct lark1s_gas_info_s {
uint32_t gas_id;
uint8_t gas_name[12];
uint32_t unit_id;
uint8_t unit_name[8];
uint32_t range;
uint32_t min_cali;
};
struct lark1s_gas_cali_data_s {
uint32_t available;
uint32_t zero_sig_cts;
uint32_t zero_ref_cts;
uint32_t zero_det_temp;
uint32_t zero_lamp_temp;
uint32_t span_concentration;
uint32_t span_sig_cts;
uint32_t span_ref_cts;
uint32_t span_det_temp;
uint32_t span_lamp_temp;
};
struct lark1s_data_s {
uint32_t det_temp;
uint32_t air_pressure;
uint32_t gas3_reading;
uint32_t cts_ref;
uint32_t cts_gas3;
int32_t gas3_compensated_reading;
};
struct lark1s_status_s {
uint16_t zero_record[4];
uint16_t span_record[4];
uint16_t active;
uint16_t restore;
};
#ifdef __cplusplus
extern "C" {
#endif
void lark1s_set_mb_address(uint8_t address);
uint16_t lark1s_get_mb_errno(void);
int lark1s_req_sn(uint8_t *buffer);
int lark1s_parse_sn(uint8_t *buffer, int length, char *sn);
int lark1s_req_gas3_info(uint8_t *buffer);
int lark1s_parse_gas3_info(uint8_t *buffer, int length, struct lark1s_gas_info_s *info);
int lark1s_req_data(uint8_t *buffer);
int lark1s_parse_data(uint8_t *buffer, int length, struct lark1s_data_s *data);
int lark1s_req_gas3_cali_zero_record(uint8_t *buffer);
int lark1s_parse_gas3_cali_zero_record(uint8_t *buffer, int length);
int lark1s_req_gas3_cali_span_record(uint8_t *buffer, uint32_t concentration);
int lark1s_parse_gas3_cali_span_record(uint8_t *buffer, int length);
int lark1s_req_gas3_cali_active(uint8_t *buffer);
int lark1s_parse_gas3_cali_active(uint8_t *buffer, int length);
int lark1s_req_gas3_cali_restore(uint8_t *buffer);
int lark1s_parse_gas3_cali_restore(uint8_t *buffer, int length);
int lark1s_req_status(uint8_t *buffer);
int lark1s_parse_status(uint8_t *buffer, int length, struct lark1s_status_s *status);
#ifdef __cplusplus
}
#endif
#endif /* __LARK1S_H__ */

View File

@ -5,8 +5,100 @@
#include <unistd.h>
#include <termios.h>
#include <string.h>
#include "../lark1s/lark1s.h"
int main() {
#define MB_ADDRESS 9
#define MB_RESP_TIME 1
#define BUFFER_SIZE 1024
uint8_t buffer_w[BUFFER_SIZE];
uint8_t buffer_r[BUFFER_SIZE];
void print_sn(int fd, uint8_t *out, uint8_t *in)
{
uint8_t sn[16];
int ret;
ret = lark1s_req_sn(out);
if (ret) {
write(fd, out, ret);
} else {
printf("Error: lark1s_req_sn failed\r\n");
}
sleep(MB_RESP_TIME);
ret = read(fd, in, BUFFER_SIZE);
ret = lark1s_parse_sn(in, ret, sn);
if (ret) {
printf("Error: lark1s_parse_sn failed, %d\r\n", ret);
} else {
printf("SN: ");
for (int j = 0; j < 16; j++) {
printf("%c", sn[j]);
}
printf("\r\n");
}
}
void print_gas3_info(int fd, uint8_t *out, uint8_t *in)
{
struct lark1s_gas_info_s info;
int ret;
ret = lark1s_req_gas3_info(out);
if (ret) {
write(fd, out, ret);
} else {
printf("Error: lark1s_req_gas3_info failed\r\n");
}
sleep(MB_RESP_TIME);
ret = read(fd, in, BUFFER_SIZE);
ret = lark1s_parse_gas3_info(in, ret, &info);
if (ret) {
printf("Error: lark1s_parse_gas_info failed, %d\r\n", ret);
} else {
printf("gas3_info.gas_id: %d\r\n", info.gas_id);
printf("gas3_info.gas_name: ");
for (int j = 0; j < 12; j++) {
printf("%c", info.gas_name[j]);
}
printf("\r\n");
printf("gas3_info.unit_id: %d\r\n", info.unit_id);
printf("gas3_info.unit_name: ");
for (int j = 0; j < 8; j++) {
printf("%c", info.unit_name[j]);
}
printf("\r\n");
printf("gas3_info.range: %d\r\n", info.range);
printf("gas3_info.min_cali: %d\r\n", info.min_cali);
}
}
void print_data(int fd, uint8_t *out, uint8_t *in)
{
struct lark1s_data_s data;
int ret;
ret = lark1s_req_data(out);
if (ret) {
write(fd, out, ret);
} else {
printf("Error: lark1s_req_data failed\r\n");
}
sleep(MB_RESP_TIME);
ret = read(fd, in, BUFFER_SIZE);
ret = lark1s_parse_data(in, ret, &data);
if (ret) {
printf("Error: lark1s_parse_data failed, %d\r\n", ret);
} else {
printf("data.det_temp: %d\r\n", data.det_temp);
printf("data.air_pressure: %d\r\n", data.air_pressure);
printf("data.gas3_reading: %d\r\n", data.gas3_reading);
printf("data.cts_ref: %d\r\n", data.cts_ref);
printf("data.cts_gas3: %d\r\n", data.cts_gas3);
printf("data.gas3_compensated_reading: %d\r\n", data.gas3_compensated_reading);
}
}
int main(void) {
int fd;
struct termios options;
@ -25,16 +117,12 @@ int main() {
tcflush(fd, TCIFLUSH);
tcsetattr(fd, TCSANOW, &options);
uint8_t buffer_w[] = {0x09, 0x04, 0x00, 0x00, 0x00, 0x20, 0xF0, 0x9A};
uint8_t buffer_r[256];
lark1s_set_mb_address(MB_ADDRESS);
while (1) {
write(fd, buffer_w, sizeof(buffer_w));
sleep(1);
print_sn(fd, buffer_w, buffer_r);
print_gas3_info(fd, buffer_w, buffer_r);
print_data(fd, buffer_w, buffer_r);
int num_bytes = read(fd, buffer_r, sizeof(buffer_r));
for (int i = 0; i < num_bytes; i++) {
printf("%02X ", buffer_r[i]);
}
printf("\r\n");
fflush(stdout);
}