51单片机实现485通信的应用(附代码)

本文介绍了使用STC89C516RD单片机和TTL转485模块进行RS485通信的步骤,包括串口配置、波特率设置和中断函数的应用。通过设置SM2位实现多机通讯协议,允许主机和从机之间的数据交换,且提供了主从机的代码模板。
摘要由CSDN通过智能技术生成

在学习单片机的过程中,我在网络上参考了不少同学的毕业设计。其中最令我觉得有意思的就是智能家居系统,特别是我看着那些小巧的温湿度传感器和角度传感器,我就在想,如果真的应用到实际的场景中,那些传感器的线还能用杜邦线吗?起码I2C的传感器肯定是不能用了。那他们怎么扩大传输距离呢?结合在网上零零碎碎的看到什么工业控制用485,我就想着试一试,最后结果还行。哥们找遍CSDN都没找到几个免费的有用信息,实验成功后想想还是放上来给大家参考下。所以就引来了本文的主角——485通信。

RS485是电气层面上的规则,真要看起来理论一大堆。一堆人说485协议,又有一些人说485就不是协议而是标准,爱咋咋地吧,本文不谈理论,就告诉大家如何去用。

前期准备

单片机使用的是STC89C516RD+,引脚与89C52一样,就是程序存储较大。资料来源于STC。

在淘宝上购买了TTL转485模块,以下是接线示意图。有了这个模块,我们就可以按照配置串口的方式来实现485通讯。有基础的可以直接偷掉电路图画到自己板子上哈哈

485通讯在应用上使用的是双绞线,既可以去淘宝上购买485专用线,也可以在实验阶段使用网线验证。网线中包含着四对双绞线,对个人而言容易获得。在实验无干扰的情况下地线可以不接。这次我使用了60M的网线,实验结果非常OK。

串口配置

首先,要配置串口控制寄存器SCON和电源控制寄存器PCON。

SM0、SM1: 根据手册上的说明,如果我们想要实现波特率可变的通信,就要使用

以下是一个简单的 C++ 示例代码,演示如何在工控机和 51 单片机之间通过 485 总线进行通信。 工控机端代码: ```cpp #include <iostream> #include <Windows.h> using namespace std; int main() { HANDLE hCom = CreateFile("COM1", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); if (hCom == INVALID_HANDLE_VALUE) { cerr << "Failed to open COM1 port" << endl; return 1; } DCB dcb; dcb.DCBlength = sizeof(dcb); GetCommState(hCom, &dcb); dcb.BaudRate = CBR_9600; dcb.ByteSize = 8; dcb.Parity = NOPARITY; dcb.StopBits = ONESTOPBIT; SetCommState(hCom, &dcb); char txData[] = { 0x01, 0x03, 0x00, 0x00, 0x00, 0x02, 0xc4, 0x0b }; DWORD bytesWritten; WriteFile(hCom, txData, sizeof(txData), &bytesWritten, NULL); char rxData[256]; DWORD bytesRead; ReadFile(hCom, rxData, sizeof(rxData), &bytesRead, NULL); for (int i = 0; i < bytesRead; i++) { printf("%02X ", rxData[i]); } putchar('\n'); CloseHandle(hCom); return 0; } ``` 51 单片机代码: ```cpp #include <reg52.h> sbit RS485_EN = P2^0; void initRS485() { SCON = 0x50; // 8-bit UART, no parity, 1 stop bit TMOD &= 0x0F; // T1 in 8-bit auto-reload mode TMOD |= 0x20; TH1 = 0xFD; // 9600 baud rate TL1 = 0xFD; TR1 = 1; // enable timer1 RS485_EN = 0; // set RE/DE to receive } void sendByte(unsigned char byte) { SBUF = byte; while (!TI); // wait until byte is sent TI = 0; // clear the flag } unsigned char recvByte() { while (!RI); // wait until byte is received RI = 0; // clear the flag return SBUF; } void main() { initRS485(); while (1) { unsigned char rxData[256]; unsigned char rxLen = 0; while (1) { // wait for the start byte while (recvByte() != 0x01); // check the function code if (recvByte() != 0x03) { continue; } // read the data length unsigned char len = recvByte(); // read the data for (unsigned char i = 0; i < len; i++) { rxData[i] = recvByte(); } rxLen = len; // calculate the CRC unsigned short crc = 0xFFFF; for (unsigned char i = 0; i < len + 2; i++) { crc ^= recvByte(); for (unsigned char j = 0; j < 8; j++) { if (crc & 0x0001) { crc = (crc >> 1) ^ 0xA001; } else { crc = crc >> 1; } } } if (crc == 0) { break; } } // send the response unsigned char txData[] = { 0x01, 0x03, rxLen, 0x00, 0x01, 0x02, 0x34, 0x12 }; for (unsigned char i = 0; i < sizeof(txData) - 2; i++) { sendByte(txData[i]); } // append the CRC unsigned short crc = 0xFFFF; for (unsigned char i = 0; i < sizeof(txData) - 2; i++) { crc ^= txData[i]; for (unsigned char j = 0; j < 8; j++) { if (crc & 0x0001) { crc = (crc >> 1) ^ 0xA001; } else { crc = crc >> 1; } } } sendByte(crc & 0xFF); sendByte(crc >> 8); // enable receiver RS485_EN = 0; } } ``` 注意:这只是一个简单的示例代码,实际应用可能需要根据具体情况进行修改。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值