⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 本文提出了基于MCU和RS485总线的嵌入式系统的常用设计方法
💻 C
字号:
/* 通讯规则: 
  01:时钟7.3728 MHz/波特率9600/9个数据位/奇校验/1个停止位/硬件多机通讯功能/ 
  02:通讯连接采用硬件MAX485,双向单工
  03:MAX485的RE/DE并联接到单片机的PD2脚(高电平发送/低电平接收)
  04:所有MAX485的A脚并联/B脚并联/D脚接TXD/R脚接RXD
  05:每个上行/下行的数据包的字节个数都是一样的(通讯数据量) 
  06:数据包格式: 地址_数据1_数据2_数据3_数据n_CRC8校验码
  07:所有单元的数据接收都是采用中断+查询的方式 
  08:总是由主机向从机下发一个数据包,从机收到数据包并校验正确后向主机回复一个数据包 
  09:不管是主机还是从机,如果收到的数据包有任何错误,都将丢弃该数据包,等效于没有接收 
  10:通讯采用主机轮询方式,从机之间不能相互通讯,必须通过主机才能交换数据 
  11:无效地址是0,主机地址是1,从机地址是11.12.13...广播地址是255 
*/

#include<iom16v.h>
#include <macros.h> 
#include "1602.h"
#include "delay.h"

#define amount   10
#define address  1

unsigned char send[amount];
unsigned char inbox[amount];
unsigned char n=0;//记忆叫断接收的次数



  //end 

//波特率9600/9个数据位/1个停止位/奇校验/收发开启/接收中断/地址过滤 
void usart_init(void) 
{   
  UCSRA=0x01; 
  UCSRB=0x9C; 
  UCSRC=0xB6; 
  UBRRH=0x00; 
  UBRRL=47;  
}

unsigned char crc8(unsigned char *ptr, unsigned char len)   
{  
  unsigned char i;  
  unsigned char crc=0;  
  while(len--!=0)   
   {  
     for(i=1; i!=0; i*=2)  
      {  
        if((crc&1)!=0) {crc/=2; crc^=0x8C;} 
        else crc/=2;  
        if((*ptr&i)!=0) crc^=0x8C;      
       }   
     ptr++;  
    }  
  return(crc);  
}

#pragma interrupt_handler RXC_Int: 12
void RXC_Int(void) 
{
 if( UCSRA&28 ){ n=UDR; n=0; UCSRA|=0x01; } else          //接收出错就重新打开地址帧筛选功能 
  {
    if( UCSRB&2  ) n=0;                                    //检测到地址信息时计数清零
    inbox[n]=UDR;  n++;                                    //把接收到的数据保存到收件箱   
    if( inbox[0]==address ) UCSRA&=254; else UCSRA|=0x01;  //地址筛选  
  }
}  

void usart_out(unsigned char *datas,unsigned char n) 
{ 
  unsigned char i=0;   
  PORTD |=(1<<PD4);                                        //使MAX485处于发送状态 
  while(i<n)                                               //一共发送n个数据 
  {   
    if(i==0) UCSRB|=1; else UCSRB&=254;    
    UDR=*(datas+i);                                        //装载数据开始发送  
    while((UCSRA&64)==0);                                  //等待发送结束 
    UCSRA|=64;                                             //清除发送结束标志 
    i++;                                                   //发送次数统计 
  }  
  PORTD&=~(1<<PD4);                                        //使MAX485处于接收状态 
} 
void main()
{
 usart_init(); 
 LCD_init();   //液晶初始化
 DDRD |=(1<<PD4);
 DDRA |=0x07;
 SEI();        //打开全局中断,需要macros.h支持
 LCD_write_string(0,0,"Send:");
 LCD_write_string(0,1,"Rev:");
 while(1){
    send[3]=9;                     //更新发件箱的数据(测试代码)
    send[0]=11;                                            //指向从机地址
    send[amount-1]=crc8(send,amount-1);                    //计算发件箱数据的crc8校验码 
    usart_out(send,amount);                                //将发件箱的数据send[]发送出去; 
    LCD_write_string(5,0,send);
    n=0;                                                   //计数复位,准备接收新数据
    delay_nms(15);                                          //等待从机回复数据,这个时间要计算好
    
    if(n==amount && inbox[amount-1]==crc8(inbox,amount-1)) //接收正确处理与测试
    {  
      PORTA|=(1<<PA1); delay_nms(10); PORTA&=~(1<<PA1);
    }
    else                                                   //接收错误处理与测试
    {
      PORTA|=(1<<PA2); delay_nms(10); PORTA&=~(1<<PA2);
    }   
   }
 }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -