单片机
返回首页

8051/2单片机常用的本地通讯方式 UART,RS485,I2C,SPI 之 Modbus 485 2

2022-05-19 来源:eefocus

一 ,说明


1. 串口UART, 波特率:9600


接设备的时候,一般只接GND RX TX,不会接Vcc,避免与目标设备上的供电冲突。


1.1 RS485标准( +2V ~ +6V:1 / -6V ~ -2V:0)


1.2 RS232标准( -15V ~ -3V:1 / +3V  ~ +15V:0),需要MAX232进行电平反转后,才能与MCU进行通讯


1.3 TTL标准( 2.4V--5V:1 /  0V--0.5V:0 )


二、演示

三、代码


/**

* 8051/2 DEMO 3

* 常用的本地通讯方式

* 1. 串口UART, 波特率:9600

* 接设备的时候,一般只接GND RX TX,不会接Vcc,避免与目标设备上的供电冲突。

* 1.1 RS485标准( +2V ~ +6V:1 / -6V ~ -2V:0)

* 1.2 RS232标准( -15V ~ -3V:1 / +3V  ~ +15V:0),需要MAX232进行电平反转后,才能与MCU进行通讯

* 1.3 TTL标准( 2.4V--5V:1 /  0V--0.5V:0 )

* 2. I2C(SCL,SDA)

* 3. SPI (SCLK,SDO,SDI) 全双工

*/

 

#include 'REG52.H'

#include

 

typedef unsigned char U8;

typedef unsigned short U16;

 

/** 

* PART 1.1 RS485  

* VCC - 3.3v, GND - 0, RX, TX  

* IO口:P3^0 和 P3^1

**/

 

 

//初始化485

void rs485_init()

{

   SCON = 0x50;

   TMOD = 0x20; //选择 定时器1

   //装在波特率 高8位和低8位,9600

   TH1 = 0xFD;

   TL1 = 0xFD;

   ES = 1; //打开串口中断

   TR1 = 1; //打开定时器1

   EA = 1; //打开总中断

}

 

//485 接收单个字符

U8 rs485_get_char()

{

   U8 rx_data = 0;

   while(0==RI); //0 串口没有数据

   //如果是1

   rx_data = SBUF;

   RI=0;

   return rx_data;

}

//485发送一个字符

void rs485_send_char(char str)

{

   SBUF = str; //将待发送的字符串放入缓冲器

   while(TI==0); //等待完发送

   TI=0;       // 发送中断标志 清0

}

 

//crc modbus

U16 code crc_table[] = {

   0x0000, 0xcc01, 0xd801, 0x1400,

   0xf001, 0x3c00, 0x2800, 0xe401,

   0xa001, 0x6c00, 0x7800, 0xb401,

   0x5000, 0x9c01, 0x8801, 0x4400

};

U16 rs485_crc16(U8 *arr,U8 len)

{

   U16 crc = 0xffff;

U8 i;

U8 temp;

   for(i = 0; i < len; i++) {

temp = *arr++;

 

      rs485_send_char(temp); //发送数据

 

crc = crc_table[(temp ^ crc) & 15] ^ (crc >> 4);

crc = crc_table[((temp >> 4) ^ crc) & 15] ^ (crc >> 4);

}

   return crc;

}

 

//485发送16进制数组, arr 数组,len 发送长度,末尾会自动追加 CRC16 Modbus计算值

void rs485_send_bytes(U8 *arr,U8 len)

{

   U16 crc16 = rs485_crc16(arr,len);

   U8 r8 = (U8)(crc16 & 0xff ); //低8位

   U8 l8 = (U8)(crc16 >> 8); //高8位

   rs485_send_char(r8);

   rs485_send_char(l8);

}

 

//485中断业务处理 

void rs485_handle() interrupt 4

{

   //业务处理,字符和并到数组

   U8 rx_datas[9]; //收8个16进制数

   U8 i=0;

   for(i=0;i<8;i++){

      U8 rx_data = rs485_get_char();

      rx_datas[i] = rx_data;

   }

   //如果是 02 03 00 00 00 01 84 39, 则返回 02 03 02 04 05 XX XX  其中XX XX为CRC16校验码

   if(

      rx_datas[0]==0x02 && rx_datas[1]==0x03 && rx_datas[2]==0x00 && 

      rx_datas[3]==0x00 && rx_datas[4]==0x00 && rx_datas[5]==0x01 &&

      rx_datas[6]==0x84 && rx_datas[7]==0x39

   )

   {

      U8 code hexdata[] = {0x02,0x03,0x02,0x04,0x05};

      rs485_send_bytes(hexdata,5);

   } 

}

 

 

void main()

{

    rs485_init();

    

    while (1){

    }

}

进入单片机查看更多内容>>
相关视频
  • RISC-V嵌入式系统开发

  • SOC系统级芯片设计实验

  • 云龙51单片机实训视频教程(王云,字幕版)

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

精选电路图
  • 单稳态控制电路设计与分析

  • 光控电路设计与分析

  • IGBT模块通过控制门极阻断过电流

  • 开关电源的基本组成及工作原理

  • 基于M66T旋律发​​生器的电路图解析

  • 一个简单的红外耳机电路

    相关电子头条文章