讲师博文
FreeModbus温湿度传感器试验 来源 : 未知     2018-08-16

【实验目的】

● 学习STM32的Cortex-M0系列芯片的使用

● 学习IAR开发软件的使用方法,如仿真调试

● 通过本实验掌握ModBus协议

【实验环境】

● STM32F051 Cortex-M0模块

● IAR开发工具和相应的仿真器

● PC机 XP、win7/win8/win10(32/64)

【实验内容】

利用STM32F051库函数编写ModBus实验程序,实现M0模块上电默认为从机,当接收到命令时可以,可以自动切换为主机,向温湿度传感器发送请求命令,温湿度传感器响应返回数据。M0通过无线ZigBee(串口2)发送出去。ZigBee协调接收无线数据并显示到串口上。

【实验原理】

图 STM32F051原理图

温湿度传感:

【实验步骤】

完成第“开发环境搭建”章节的IAR环境搭建,就可以做传感器实验了,首先打开光盘中的传感器工程文件。

工程源码路径:【智能农业光盘资料\01程序源码\03M0节点源码\01Modbus_STM32F051(温湿度1 01)\Project】

编译下载程序(先编译后下载)

打开“设备管理”。

查看COM口,打开串口调试助手。波特率9600,串口号COM8。

M0模块与485总线板子连接在一起。并确保温湿度传感器连接到485上。

【实验现象】

利用串口调试助手,串口转485调试板,485总线的线和调试板相连接。

在串口发送区发送请求命令,返回读到的温湿度环境信息:

发送请求命令:01 03 00 00 00 02 C4 0B

根据ModBus协议:01:设备地址 03:设备地址 00 00:起始寄存器地址 00 02:从起始地址,读取2个地址,读取数据值。C4 0B: CRC校验

返回环境信息:01 03 04 00 B8 01 51 BA 7A

根据ModBus协议:01:设备地址 03:设备地址 04:数据长度 00 B8:温度值 01 51:湿度值

BA 7A:CRC校验

【实验代码】

定义主从关系,默认ModBusSlave = 1,此时程序为从机,和温湿度传感器是并联。

COBOL Code

uint8_t ModBusSlave = 1;

uint8_t ModBusMaster = 0;

当从机接收到命令时,会有从机转变为主机,主动采集温湿度传感器环境信息。并1S上报一次环境数据。

(1)接收到从机转主机的命令(485发来的数据):

00 06 00 03 00 01 B9 DB

广播地址 + 06 + 0003 + 00 01 + CRC校验

06表示ModBus 写保持寄存器命令。

0003表示写第几个寄存器。

0001表示向寄存器中写的内容。为1有485网络切换到ZigBee网络(主机模式)

B9DB表示CRC校验

ZigBee协调器插到电脑上USB,通过串口调试助手打开ZigBee协调器的COM口(波特率115200),显示接收到M0传感器采集的数据。数据格式是21 5A 打头数据,含有设备地址、传感器类型和数据。

M0上传的协议数据如下:

uint8_t usSendBuf[SendLong] = {0x21,0x5A, SlaveID,0x00,0x74,0x00,0x00,0x00,0x00,0x00,0x00,0x6B};

第5、6、7位为数据位,其他的是固定写法。

接收数据

数据:215A0100740000000000006B

位号:01234567891011

含义:标记网络从机ID保留类型采集的数据保留位

第0字节位是标记位,用于判断次数据包是否是合法的需要的数据包。

第1字节位是用于区分网络类型的,分为二种网络:zigbee-5A,RS485-52。

第2字节表示的是节点的地址位(ID),1~255之间。

第4字节位是节点的类型,包括::温湿度-74,土壤温湿度-74,光感-6C,红外-69,C02-63,加热器-57,加湿器-48,通风-46,照明-4C,喷湿-44,遮阳-53,报警-41 等多种类型的传感器。

(2)接收到主机转从此机的命令(ZigBee发来的数据):

数据:236352626F7901

位号:0123456

含义:标记标记网络预留预留预留

第0,1字节位是标记位,用于判断次数据包是否是合法的需要的数据包。

第0字节标记位:0x23(#) 表示此数据为命令字段

第1字节标记位:0x63(c) 表示此数据为网络切换命令

第2字节位是网络位:用于判断要切换到那种网络

0x5A(Z):zigbee网络

0x52(R):rs485网络

第3字节位:此系统预留--必须为0

第4,5字节位:此系统预留--必须为0

第6字节位:此系统预留--必须为0

主程序

int main(void)

{

uint8_t i;

uint8_t RxData;

uint8_t Senddata[13] ={0};

uint8_t sendflag = 0;

/*!< At this stage the microcontroller clock setting is already configured,

this is done through SystemInit() function which is called from startup

file (startup_stm32f0xx.s) before to branch to application main.

To reconfigure the default setting of SystemInit() function, refer to

system_stm32f0xx.c file

*/

/* SysTick end of count event each 10ms */

RCC_GetClocksFreq(&RCC_Clocks);

SysTick_Config(RCC_Clocks.HCLK_Frequency / 100);

/* Add your application code here

*/

LED_Init();

//初始化继电器

Relay_Init(Relay1_PORT,Relay1_PIN);

Relay_Init(Relay2_PORT,Relay2_PIN);

Relay_Init(Relay485_PORT,Relay485_PIN);

Usart_Init(USART2,115200);

if(ModBusMaster)

Usart_Init(USART1,9600);

if(ModBusSlave)

{

//模式 从地址 端口 波特率 校验位

eMBInit(MB_RTU, MSlaveID, 0x01, 9600, MB_PAR_NONE);

//启动FreeModbus

eMBEnable();

}

QueueInit(&FIFO_485);

/* Infinite loop */

while (1)

{

if(ModBusMaster)

{

//向ZigBee发送接收到ModBus的数据 ModBus ====》ZigBee

if(FIFO_485.count >= 1)

{

QueueOut(&FIFO_485,&RxData);

if(RxData == SlaveID)

{

Senddata[0] = RxData;

QueueOut(&FIFO_485,&RxData);

if(RxData == 0x03)

{

Senddata[1] = RxData;

for(i=2;i<12;i++)

{

QueueOut(&FIFO_485,&RxData);

Senddata[i] = RxData;

}

usSendBuf[5] = 0;

usSendBuf[6] = (Senddata[3] << 8) | (Senddata[4] /10);

usSendBuf[7] = (Senddata[5] << 8) | (Senddata[6] /10);

for(i=0;i < 12;i++)

{

USART_SendData(USART2, usSendBuf[i]);

/* Loop until the end of transmission */

while (USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET)

{}

}

}

}

}

if(FIFO_485.count == 0 )

{

Delay(150);

//发送ModBus命令,通过ZigBee上报给网关(不来)

ModBusSend(HUM1_buf);

}

//发送zigbee串口2接收到的ModBus命令---->请求传感器命令

if(RxZigbeelen == RxZigbeelong)

{

//判断接收zigbee的数据,是否为485继电器切换命令

if((Rx_Zigbee_buf[1] == 0x63) && (Rx_Zigbee_buf[2] == 0x52))

{

USART_Cmd(USART1, DISABLE);

USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);

//继电器切换为常闭状态

GPIO_ResetBits(Relay485_PORT, Relay485_PIN);

//清空zigbee接收缓冲区的数据

memset(Rx_Zigbee_buf,0,64);//sizeof(char)*RxModbuslen);

RxZigbeelen = 0;

ModBusSlave = 1;

ModBusMaster = 0;

if(ModBusSlave)

{

//模式 从地址 端口 波特率 校验位

eMBInit(MB_RTU, MSlaveID, 0x01, 9600, MB_PAR_NONE);

//启动FreeModbus

eMBEnable();

}

}//判断是否为控制继电器命令(开)

else if(Rx_Zigbee_buf[3] == 'Z'){

if(Rx_Zigbee_buf[4] == MSlaveID){ //判断控制的地址

if(Rx_Zigbee_buf[6] == '1'){ //继电器的开

//控制继电器拨到常开 PB.8

GPIO_SetBits(Relay2_PORT,Relay2_PIN );

//清空zigbee接收缓冲区的数据

memset(Rx_Zigbee_buf,0,64);//sizeof(char)*RxModbuslen);

RxZigbeelen = 0;

}else if(Rx_Zigbee_buf[6] == '0'){

//控制继电器拨到常开 PB.8

GPIO_ResetBits(Relay2_PORT,Relay2_PIN );

//清空zigbee接收缓冲区的数据

memset(Rx_Zigbee_buf,0,64);//sizeof(char)*RxModbuslen);

RxZigbeelen = 0;

}

}

}

}

else if(RxZigbeelen > RxZigbeelong)

{

memset(Rx_Zigbee_buf,0,64);//sizeof(char)*RxModbuslen);

RxZigbeelen = 0;

}

//如果485切换成功,则灯灭

if(Led_flag == 1)

{

LED2_OFF();//关闭led灯

Led_flag = 0;

}

}

if(ModBusSlave)

{

eMBPoll( );

//从机接收到数据判断,可改变主从模式,下面关闭从模式

if((usRegHoldingBuf[3] & 0xFF) == 0x01)

{

USART_Cmd(USART1, DISABLE);

USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);

//主从切换的继电器切换到常开

GPIO_SetBits(Relay485_PORT,Relay485_PIN );

if(ModBusSlave)

{

eMBDisable();

ModBusSlave = 0;

ModBusMaster = 1;

if(ModBusMaster)

Usart_Init(USART1,9600);

Delay(5);

}

//清空

usRegHoldingBuf[3] &= ~(1 << 0);

}

if(Led_flag == 0)

{

LED2_ON();//开led灯

Led_flag = 1;

}

}

}

}

扫码申领本地嵌入式教学实录全套视频及配套源码

上一篇:C语言中常见的笔试题

下一篇:大型程序管理神器之CMake

400-611-6270

Copyright © 2004-2024 华清远见教育科技集团 版权所有
京ICP备16055225号-5京公海网安备11010802025203号