RS485 Modbus协议 采集传感器数据
硬件1、传感器:为液压传感器,12vDC,RS485数据输出,采用Modbus协议通信
2、电路:根据传感器属性,电路主要是两部分,通信电路和电源电源
(1)485电路:由于485是半双工通信,需要控制收发,所以索性在把电路设计成自动收发电路接跳线帽W1、W2即使用RS485收发,不接就是普通串口收发。RE和DE是收发使能,选择485模式:3_TXD常高,使能接受;当发送数据时,数据的起始位(下降沿)将3_TXD引脚电平拉低,将顺便使能发送。传感器接3_A、3_B。 (2)开关电路:主要是为了控制传感器开关,以降低功耗
测试485电路
1、485电路测试程序
对于单片机来说,其实仍然是串口通信,只不过经过485芯片实现了RS232电平→RS485电平。 初始化串口3,并在初始化时开启串口接收中断初始化串口3,并在初始化时开启串口接收中断 void MX_USART3_UART_Init(void)
{
huart3.Instance = USART3;
huart3.Init.BaudRate = 9600;
huart3.Init.WordLength = UART_WORDLENGTH_8B;
huart3.Init.StopBits = UART_STOPBITS_1;
huart3.Init.Parity = UART_PARITY_NONE;
huart3.Init.Mode = UART_MODE_TX_RX;
huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart3.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart3) != HAL_OK)
{
Error_Handler();
}
Usart3RecIT();//开启串口3接收中断
start_capture();//发送请求帧
}
接收中断回调函数中保存串口数据
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance == USART3){//RS485设备
HAL_UART_Receive_IT(&huart3, &uart3Data, 1);
uart3WriteByte(uart3Data);//接收到的数据写入缓存
uart3Data** = 1;
}
} 缓存数据:环形队列,不啰嗦
#define SENSOR_485_DATA_BUFFER_MAX_LENGTH60
typedef struct {
uint16_t front;
uint16_t rear;
uint8_t* buffer;
uint32_t maxSize;
}Buffer_t;
static Buffer_t sensor485Buffer;
uint8_tsensor485DataBuffer;//缓存数组
void uart3WriteByte(uint8_t data)
{
Buffer_Puts(&sensor485Buffer,&data,1);//入队
}
bool Buffer_Puts(Buffer_t* buffer, uint8_t* data, uint16_t length)
{
if (buffer->maxSize - Buffer_Size(buffer) <= length)//队满
return false;
for (uint16_t i = 0; i<length; ++i)//队列未满
{
buffer->rear = (buffer->rear + 1) % buffer->maxSize;
buffer->buffer = data;//进队
}
return true;
}
这个接口,是为了向传感器发送指令,请求传感器数据,指令需要查看传感器指令定义,属于协议那部分,先测试
void start_capture(){
uint8_t TxData= "1111111111";
HAL_UART_Transmit(&huart3,TxData,10,0xffff);
HAL_Delay(100);
}
在Keil中Debug,用串口助手向单片机发送数据,查看数组sensor485DataBuffer接收到了,接收是可以了
但是我遇到了问题,上位机没有接受到2-(4)发送的“1111111111”,单片机发送出现了问题
(1)分别检查TX、R15、R16都有信号出来 第一反应是485芯片发送使能没有成功,检查RE和DE引脚,果然一直是低电平,说明三极管一直导通,没有阻塞过
无奈之下,干脆用反相器替换了三极管然后,就可以了…
加入Modbus协议
1、协议原理
(1)以上测试说明:链路层硬件协议√; (2)但是问题来了,只有硬件协议可以和传感器通信吗? 当然不行,传感器又不是电脑,它没有上位机:你点一下发送就把数据发出去了。这个时候需要单片机来告知它发送。所以我们还需要:链路层软件协议Modbus协议√; 我们选取Modbus协议中对我们编程有帮助的几点:
以帧的形式通信,有ASCII和RTU两种模式,帧中的地址、功能码等都是一个或多个字节,每个字节是一个8位串口数据
如果一个串口连接多个4856设备,可以通过地址区分不同485设备,当然串口资源充足也可以挂载在多个串口上 RTU模式通过两帧数据的时间间隔,区分前后两帧数据,如果串口数据间隔大于3.5个字节,那么就认为一帧数据结束了,在9600bps/s波特率下,传输3.5个字节时间大概为4ms;ASCII模式读回车换行就行了
页:
[1]
2