本帖最后由 跑龙套的保 于 2018-8-2 15:01 编辑
就那么难么,问了那么久了,用了TTL转485,你就别把它当做485通讯的了,arduino 里的程序就是读写串口,直接帮你写好吧
[mw_shl_code=cpp,true]#include <SoftwareSerial.h>
const byte rxPin = 2;
const byte txPin = 3;
//ttl转485接软串
SoftwareSerial TTL2485(rxPin, txPin);
// #define TTL2485 Serial
#define MAX_PACKETSIZE 128 //自定义的缓冲buff长度
uint8_t softUart_Receive_Buff [ MAX_PACKETSIZE ]; //定义缓冲buff
unsigned int softUart_Receive_Index = 0; //收到的字节实际长度
unsigned long preSoftUartTime = 0; //记录读取最好一个字节的时间点
/*
计算crc16校验
modbus
*/
uint16_t calcCRC16 (uint8_t *ptr, size_t size)
{
unsigned short a, b, tmp, CRC16, V;
CRC16 = 0xffff; //CRC寄存器初始值
for (a = 0; a < size; a++) //N个字节
{
CRC16 = *ptr ^ CRC16;
for (b = 0; b < 8; b++) //8位数据
{
tmp = CRC16 & 0x0001;
CRC16 = CRC16 >> 1; //右移一位
if (tmp)
CRC16 = CRC16 ^ 0xa001; //异或多项式
}
*ptr++;
}
//大小端转换
V = ((CRC16 & 0x00FF) << 8) | ((CRC16 & 0xFF00) >> 8); //高低字节转换
return V;
}
/*
校验crc16
modbus
*/
bool checkCRC16(uint8_t *p, size_t len)
{
if (p[len - 2] * 256 + p[len - 1] == calcCRC16(p, len - 2))
return true;
else
return false;
}
/*
16进制转字符串
*/
void printHex(uint8_t *p, uint16_t len)
{
char *pbuff = (char*)malloc(len * 3 + 1);
if (pbuff == NULL ) return;
pbuff[0] = 0x00;
char t[5];
for (int i = 0; i < len; i++)
{
sprintf(t, "%02X ", p);
strcat(pbuff, t);
}
Serial.println("[printHex]");
Serial.println(pbuff);
free(pbuff);
}
/*
处理串口数据函数,可以在函数内编写处理函数数据的程序
*/
void parseSoftUartPackage(uint8_t *p , int len) {
//打印日志到串口
Serial.print(F("[SoftUart Read]:"));
printHex(p, len);
if (len != 8) {
Serial.println(F("[ERROR]:len != 8"));
return;
}
if (!checkCRC16(p, len)) {
Serial.println(F("[ERROR]:check CRC16 error"));
return;
}
if(p[1] == 0x03){
Serial.println(F("cmd 03 responded successfully"));
//发送启动指令
uint8_t cmd06[8] = {0x01,0x06,0x00,0x00,0x00,0x01,0x48,0x0a};
send2SoftUart(cmd06,8);
}
else if(p[1] == 0x06){
Serial.println(F("cmd 06 responded successfully"));
}
}
//发送数据到串口
void send2SoftUart(uint8_t *p, size_t len)
{
Serial.print(F("[send to SoftUart ]:"));
printHex(p, len);
TTL2485.write(p,len);
}
/*
软串串口数据接受进程
*/
void doSotfUartTick()
{
if (TTL2485.available())
{ //读取串口数据
//每次读取一个字节的数据存储在这个buff中
softUart_Receive_Buff [ softUart_Receive_Index ++ ] = TTL2485.read();
//记录下读取这个数据的时间点
preSoftUartTime = millis();
//判断读取到的数据长度是否超过设定的记录长度,超过长度时间点往前200ms 立即执行分析函数
if (softUart_Receive_Index >= MAX_PACKETSIZE - 1) {
softUart_Receive_Index = MAX_PACKETSIZE - 2;
preSoftUartTime = preSoftUartTime - 200;
}
}
//判断收到的最后一个字节后超过100ms开始执行分析函数
if (softUart_Receive_Index > 0 && (millis() - preSoftUartTime >= 100))
{ //处理串口数据
//把buff最后一个字节设为0,在字符串处理中很有用
softUart_Receive_Buff [ softUart_Receive_Index ] = 0x00;
TTL2485.flush();
//执行串口数据处理函数
parseSoftUartPackage(softUart_Receive_Buff, softUart_Receive_Index);
softUart_Receive_Index = 0;
}
}
void setup() {
TTL2485.begin(9600);
Serial.begin(9600);
//发送查询指令
uint8_t cmd03[8] = {0x01,0x03,0x00,0x02,0x00,0x01,0x25,0xca};
send2SoftUart(cmd03,8);
}
void loop()
{
//调用串口数据处理进程
doSotfUartTick();
}[/mw_shl_code] |