基于AVRmega128的modbus程序
mega128程序之IIC24C08

#include <mega128.h>#include <delay.h>#define TWIE 0#define TWEN 2#define TWWC 3#define TWSTO 4#define TWSTA 5#define TWEA 6#define TWINT 7#define TWPS0 0#define TWPS1 1#define TWS3 3#define TWS4 4#define TWS5 5#define TWS6 6#define TWS7 7#define TWGCE 0/*********主机发送模式状态码***********/#define START 0X08#define RE_START 0X10#define MT_SLA_ACK 0X18#define MT_SLA_NOACK 0X20#define MT_DATA_ACK 0X28#define MT_DATA_NOACK 0X30#define MT_ACK_FAUIL 0X38/*********主机接收模式状态码***********/#define MR_SLA_ACK 0X40#define MR_SLA_NOACK 0X48#define MR_DATA_ACK 0X50#define MR_DATA_NOACK 0X58/*********24C01地址***********/#define RD_DEVICE_ADDR 0XA1#define WD_DEVICE_ADDR 0XA0/******主模式写和读**************/#define start() (TWCR =(1<<TWINT)|(1<<TWSTA)|(1<<TWEN)) // 启动#define stop() (TWCR =(1<<TWINT)|(1<<TWSTO)|(1<<TWEN)) // 停止#define wait() {while (!(TWCR & (1<<TWINT)));} // 等待中断发生#define test_ack() (TWSR & 0xF8) // 检测状态码#define set_ack() (TWCR |= (1<<TWEA)) // 做出ACK应答#define set_noack() (TWCR &= ~(1<<TWEA)) // 做出NOACK应答#define twi() (TWCR = (1<<TWINT)|(1<<TWEN)) // 再启动#define write_8_bit(x) {TWDR = (x);TWCR = (1<<TWINT)|(1<<TWEN);} // 写数据/*********显示端口定义***********/#define DIS_UNM PORTC#define wei_en PORTG|=0x04#define wei_cle PORTG&=0XFB#define duan_en PORTA|=0X80#define duan_cle PORTA&=0X7Fvoid PORT_INIT(void){DDRA=0XFF;PORTA=0X00;DDRC=0XFF;PORTC=0X00;DDRG=0XFF;PORTG=0X00;DDRD=0X00;PORTD=0X00;}void TWI_INIT(void);unsigned char IIC_WRITE(unsigned char wdata,unsigned char addr);unsigned char IIC_READ(unsigned char addr);void LED_display(unsigned int temp_data);unsigned char SEG7[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};//共阴极unsigned char qian,bai,shi,ge,qian_data,bai_data,shi_data,ge_data,display_flag; void main(void){unsigned char i=0;PORT_INIT();TWI_INIT();i=IIC_READ(6);//delay_ms(15);i++;IIC_WRITE(i,6);//delay_ms(10);while(1){LED_display(i);}}void TWI_INIT(void){TWBR = 0X30;TWCR = 0X04;TWSR = 0X00;}unsigned char IIC_WRITE(unsigned char wdata,unsigned char addr){start();wait();if(test_ack()!=START) //判断是否是启动信号return 1;write_8_bit(WD_DEVICE_ADDR);//delay_ms(5); //写器件地址----找器件wait();if(test_ack()!=MT_SLA_ACK) //器件是否应答了return 1;write_8_bit(addr); //delay_ms(5); // 写器件中存储地址wait();if(test_ack()!=MT_DATA_ACK) //是否应答return 1;write_8_bit(wdata);// delay_ms(5); //向器件存储地址中写数据wait();if(test_ack()!=MT_DATA_ACK) //return 1;stop();return 0;}unsigned char IIC_READ(unsigned char addr){unsigned char temp;start();wait();if(test_ack()!=START)//return 1;write_8_bit(WD_DEVICE_ADDR);//delay_ms(5);//写器件地址----找器件wait();if(test_ack()!=MT_SLA_ACK) //return 1;write_8_bit(addr); // delay_ms(5); // 写器件中存储地址wait();if(test_ack()!=MT_DATA_ACK) //return 1;start(); //wait();if(test_ack()!=RE_START) //return 1;write_8_bit(RD_DEVICE_ADDR); //delay_ms(5); //读器件地址--读命令wait();if(test_ack()!=MR_SLA_ACK)// 主机接收return 1;twi();//重新启动IICwait();if(test_ack()!= MR_DATA_NOACK)return 1;temp=TWDR; //读出数据赋给变量stop();delay_ms(2); //此延时非同寻常!!! return temp;}void LED_display(unsigned int temp_data){qian_data=temp_data/1000;temp_data=temp_data%1000;bai_data=temp_data/100 ;temp_data=temp_data%100; //取余运算shi_data=temp_data/10 ;temp_data=temp_data%10; //取余运算ge_data=temp_data;qian=SEG7[qian_data];bai =SEG7[bai_data];shi =SEG7[shi_data];ge =SEG7[ge_data];switch(display_flag){case 0x00:duan_en;DIS_UNM=0x00;duan_cle;wei_en;DIS_UNM=0xFE;wei_cle;delay_ms(2);duan_en;DIS_UNM=ge;duan_cle;display_flag++;delay_ms(2);break;case 0x01:duan_en;DIS_UNM=0x00;duan_cle;wei_en;DIS_UNM=0xFD;wei_cle;delay_ms(2);duan_en;DIS_UNM=shi;duan_cle;display_flag++;delay_ms(2);break;case 0x02:duan_en;DIS_UNM=0x00;duan_cle;wei_en;DIS_UNM=0xFB;wei_cle;delay_ms(2);duan_en;DIS_UNM=bai;duan_cle;display_flag++;delay_ms(2);break;case 0x03:duan_en;DIS_UNM=0x00;duan_cle;wei_en;DIS_UNM=0xF7;wei_cle;delay_ms(2);duan_en;DIS_UNM=qian;duan_cle;display_flag=0;delay_ms(2); break;default:// DIS_UNM=0X00;}}。
avr单片机中使用MODBUS协议的方法

Avr单片机中使用modbus协议的方法有幸做了个项目,其中使用到了单片机和上位机通讯的程序,上位机用组态实现功能,探索了些方法,写出来和大家分享一下,这些知识本不是什么秘密,本人参考了许多资料,自己整合了一下。
每种程序都是算法多样,最终功能实现就行。
大家做单片机串口通讯时是不是总想有一种以不变应万变的思想,就是在底层单片机硬件和软件不变的情况下,去适应任何上位机软件系统,当然可以实现,这就需要用到标准的通讯协议了,以下我就和大家分享一下我做的modbus协议(单片机端),如果上位机用组态软件的情况下,你直接使用通讯协议就行它会自动和单片机通讯。
大家在设计单片机程序时首先要定义好数据结构,先构想一下需要哪些采集数据,上位机需要查询什么数据,数据的类型和全局与否,运算的精度等等。
然后把上位机需要采集的数据用一个数组管理起来,便于modbus协议的实现。
单片机里串口通讯程序尽量用查询发送,中断接收的方式,要定义发送缓冲区和接收缓冲区,以便提高系统效率。
以下程序用gcc实现,单片机用avr单片机。
ISR(USART0_RX_vect)//串口0接收中断服务程序{volatile unsigned char status,data;cli();//关中断status = UCSR0A;//ucsr0a赋值状态标志data = UDR0;//接收的数据放入data变量usart0_rx_complete=0;//接收完成标志赋值0,还没有完成if ((status & (FRAMING_ERROR0 | PARITY_ERROR0 | DATA_OVERRUN0))==0)//如果各标志位正确则,执行以下{usart0_rx_count++;//接收缓冲区指针加一switch (usart0_rx_count){case 1:if(data==add//第一个字节是地址,读入内部本机地址进行比较{usart0_rx_buf[0]=data;TIMSK0=0x01;//启动定时器0,进行超时控制}else{usart0_rx_count=0;}break;case 2:if (((data==0x03)||(data==0x01)||(data==0x05)||(data==0x10))==0)//如果第一位不等于读指令0x03,01,05,10功能码,则清接收缓冲区指针{usart0_rx_count=0;}else//等于这几个功能码则进行,则将他放入接收数组,并预计接收数组长度,不是10码时都是8个字节{usart0_rx_buf[1]=data;if (data!=0x10){rx0_buf_size=8;}}break;case 3:usart0_rx_buf[2]=data;break;case 4:usart0_rx_buf[3]=data;break;case 5:usart0_rx_buf[4]=data;break;case 6:usart0_rx_buf[5]=data;break;case 7:usart0_rx_buf[6]=data;//10码时接收的字节计数if (usart0_rx_buf[1]==0x10){rx0_buf_size=9+usart0_rx_buf[6];}break;case 8:usart0_rx_buf[7]=data;//1,用10功能码时有效的数据位,system_reg_data的数据,这里规定最多接收26个字节(不带crc)break;case 9:usart0_rx_buf[8]=data;//2break;case 10:usart0_rx_buf[9]=data;//3break;case 11:usart0_rx_buf[10]=data;//4break;case 12:usart0_rx_buf[11]=data;//5break;case 13:usart0_rx_buf[12]=data;//6break;case 14:usart0_rx_buf[13]=data;//7 break;case 15:usart0_rx_buf[14]=data;//8 break;case 16:usart0_rx_buf[15]=data;//9 break;case 17:usart0_rx_buf[16]=data;//10 break;case 18:usart0_rx_buf[17]=data;//11 break;case 19:usart0_rx_buf[18]=data;//12 break;case 20:usart0_rx_buf[19]=data;//13 break;case 21:usart0_rx_buf[20]=data;//14 break;case 22:usart0_rx_buf[21]=data;//15 break;case 23:usart0_rx_buf[22]=data;//16 break;case 24:usart0_rx_buf[23]=data;//17 break;case 25:usart0_rx_buf[24]=data;//18 break;case 26:usart0_rx_buf[25]=data;//19 break;case 27:usart0_rx_buf[26]=data;//20 break;case 28:usart0_rx_buf[27]=data;//21 break;case 29:usart0_rx_buf[28]=data;//22break;case 30:usart0_rx_buf[29]=data;//23break;case 31:usart0_rx_buf[30]=data;//24break;case 32:usart0_rx_buf[31]=data;//25break;case 33:usart0_rx_buf[32]=data;//26break;case 34:usart0_rx_buf[33]=data;//27break;case 35:usart0_rx_buf[34]=data;//28break;}if(usart0_rx_count>=rx0_buf_size)//串口0接收到了指定个数的数组则{usart0_rx_count=0;//接收缓冲区指针清零usart0_rx_complete=1;//串口0接收完标志time0_num=0;//串口0的中断次数清零。
mega128串口通讯测试程序

mega128串口通讯测试程序/********************************************************说明: 需要串口调协助实验(波特率设为9600)在串口调试助手中输入要发送的内容,点发送后M128会返回相同的数据CPU型号: ATMEGA128时钟: 8MHZ日期:2014.7.22默认9600 8 1********************************************************/#include#includevoid USART0_Init( void );void USART0_Transmit( unsigned char data );unsigned char USART0_Receive( void );void main(void){unsigned char n=0,tmp=0;DDRB |=0X10; //PB4设为输出PORTB|=0X10; //关闭PB4外接的LEDDDRF |=0X0E; //LED及数码管锁存IO口设为输出PORTF|=0X0E;DDRA=0XFF; //LED IO口设为输出PORTA=0XFF;PORTF&=0xF7; //锁存数据关闭LEDPORTA=0X00;PORTF&=0XF8; //锁存数据关闭数码管USART0_Init(); //波特率9600 初始化串口while(1){if(UCSR0A&(1<<="">{tmp=USART0_Receive(); //接收数据USART0_Transmit(tmp); //发送数据}}}void USART0_Init( void ){unsigned int tmp;UBRR0L=51; /* 设置波特率*/UCSR0B = (1<<rxen0)|(1<<="" p="" 接收器与发送器使能*=""> UCSR0C = (1<<ucsz00)|(1<<="" 个数据位,="" 设置帧格式:=""> // 数据发送【发送5 到8 位数据位的帧】void USART0_Transmit( unsigned char data ){/* 等待发送缓冲器为空*/while ( !( UCSR0A & (1<<="" p="">/* 将数据放入缓冲器,发送数据*/UDR0 = data;}// 数据接收【以5 到8 个数据位的方式接收数据帧】unsigned char USART0_Receive( void ){/* 等待接收数据*/while ( !(UCSR0A & (1<<="" p="">/* 从缓冲器中获取并返回数据*/return UDR0;}</ucsz00)|(1<</rxen0)|(1<。
Mega128单片机调试与设置

Mega128单片机调试与设置一、单片机型号为ATmega128A二、调试软件为iccavr7.22和AVRstudio4.0连调三、流程:1.在iccavr中建立工程文件。
2.在iccavr中新建一个项目,并保存。
注意保存文件名必须为.c才可以。
如下图。
3.在右上方file里面右键添加.c 文件。
4.然后编写程序。
注意一般程序包括如下库文件:#include <iom128v.h>#include <macros.h>#include <stdio.h>#include <string.h>5.在利用系统生成(build)钱,一定要进行系统相关的设置,此项非常重要,否则会出现各种问题。
特别是单片机的选取,一定要按照下图选取,选择ATmega1280是不对的。
具体设置在project -> options6.设置完毕后,建立工程。
7.无错误应该为下图8.然后打开AVRstudio,打开projectwizard -> open,然后打开后缀名为.cof 的文件,如下图所示:然后会自动生成后缀名为.aps的工程文件9.然后选择10.连接成功后直接进入到如下界面11.点击黑色的AVR进行基本的设置单片机为ATmega128,JTAG mode ,然后添加 .hex 文件。
熔丝位的设置如下,只有这几个有“√”,特别要注意将M103C 的“√”去掉。
内部1M 晶振用外部8M 晶振用注意此处要修改烧入单片机的程序名称,后缀名为 .hex ,在iccavr 建立的工程文件里添加点击program 即将程序烧写进入单片机中其他一般不要设置。
12.都设置完毕后就可以进行debug或者是烧写程序了。
Debug点击绿色按钮或者在debug里选择。
AVR_128_spi串口通信程序

UCSR1B=(1<<RXEN1)|(1<<TXEN1)|(1<<RXCIE1);//发送接收使能,接收中断使能
UCSR1C=(1<<UCSZ11)|(1<<UCSZ10);//8位数据,UCSZ12,11,10共同确定
DDRD|=BIT(3); //设置发送口为输出
}
/*串口0单字符发送,查询方式*/
{
UCSR1B = 0x00; //禁止发送和接收
UCSR1A = 0x02; //倍速异步模式 USX0=1
UBRR1L=(Crystal/8/Baud1-1)%256; //根据数据手册的计算法
UBRR1H=(Crystal/8/Baud1-1)/256; //如果不是倍速则(Crystal/16/Baud1-1)
Flag1=1;
UCSR1B|=BIT(RXCIE1);//重开接收中断
}
以下是主机部份 #include <iom128v.h> #include <macros.h> #define uchar unsigned char #define uint unsigned int #include "delay.h" #include "lcd.h" void port_init(void); //SPI initialize // clock rate: 1843199hz void spi_init(void) { SPCR = 0x74; //setup SPI
init_devices(); LCD1602_initial(); LCD1602_sendbyte(iDat,1+0x30 ); // while(1) //{ for(i=0;i<2;i++) {
mega128程序之EEPROM

/******************************************/ 1、写EEPROM
1. 关中断,等待 EEWE 为 0,上次写操作结束。(无中断可以忽略) 2. 等待 SPMCSR 寄存器的 SPMEN 为零。 3. 将新的 EEPROM 地址写入 EEAR。 4. 将新的 EEPROM 数据写入 EEDR。 5. 对 EECR 寄存器的 EEMWE 写 "1“ ,同时清零EEWE 6. 开中断。(无中断可以忽略) 7. 在置位 EEMWE 的 4 个周期内,置位 EEWE。 2、读EEPROM 1.SREG=0;//关中断 (无中断可以忽略) 2.等待上次写操作结束 3.找到EEPROM 地址写入 EEAR 4.读使能 EERE置1. 5.将EEDR中数据 送出 /*******************************************/ AUTHOR :Ash DATE : 20121024 /*********************************************/ #include <mega128.h> /****需要定义以下寄存器值,头文件中没有定义******/ #define EERE 0 #define EEWE 1 #define EEMWE 2 #define EERIE 3
INT8U EEP_READ(INT16U EE_ADD) {
INT8U edata; SREG=0; while(EECR&(1<<EEWE)); EEAR= EE_ADD; EECR|=(1<<EERE); edata = EEDR; return edata;
} void main(void) {
基于AVR ATmega128的工业网关的实现

ATmega128单片机为基于AVR RISC结构的8位低功耗CMOS微处理器。由于其先进的指令集以及单周期指令执行时间,ATmega128单片机的数据吞吐率高达1MIPS/MHz,故可以缓减系统的功耗和处理速度之间的矛盾。AVR单片机内核具有丰富的指令集和32个通用工作寄存器。所有的寄存器都直接与算术逻辑单元(ALU)相连接,使得一条指令可以在一个时钟周期内同时访问两个独立的寄存器。这种结构大大提高了代码效率,并且具有比普通的复杂指令集微处理器高10倍的数据吞吐量。ATmega128单片机内部带有128KB的系统内可编程Flash程序存储器,具有在写的过程中还可以读的能力,即同时读写(RWW); 4KB的EEPROM;4KB的SRAM;53个通用I/O端口线;32个通用工作寄存器;实时时钟(RTC);4个灵活的具有比较模式和PWM功能的定时器/记数器(T/C);2个USART;面向字节的两线接口(TWI);8通道10位ADC;可选的可编程增益;片内振荡器的可编程看门狗定时器;串行外围设备接口(SPI);与IEEE 1149.1规范兼容的JTAG测试接口,此接口同时还可以用于片上调试;6种可以通过软件选择的省电模式。
6 AVR单片机多处理器通信模式
置位UCSRA 的多处理器通信模式位(MPCM) 可以对USART 接收器接收到的数据帧进行过滤。那些没有地址信息的帧将被忽略,也不会存入接收缓冲器。在一个多处理器系统中,处理器通过同样的串行总线进行通信,这种过滤有效的减少了需要CPU 处理的数据帧的数量。MPCM位的设置不影响发送器的工作,但在使用多处理器通信模式的系统中,它的使用方法会有所不同。如果接收器所接收的数据帧长度为5 到8 位,那么第一个停止位表示这一帧包含的是数据还是地址信息。如果接收器所接收的数据帧长度为9 位,那么由第9 位(RXB8) 来确定是数据还是地址信息。如果确定帧类型的位( 第一个停止位或第9 个数据位) 为1,那么这是地址帧,否则为数据帧。在多处理器通信模式下,多个从处理器可以从一个主处理器接收数据。首先要通过解码地址帧来确定所寻址的是哪一个处理器。如果寻址到某一个处理器,它将正常接收后续的数据,而其他的从处理器会忽略这些帧直到接收到另一个地址帧。
DS12C887的AVRmega128驱动程序

uchar ge=0,shi=0,bai=0,qian=0;
void main()
{
uchar miao,fen,shi,nian,yue,ri;
init();
RESET_887();
* 名称 : delay()
* 功能 : 8M晶振时延时1ms
* 输入 : 时间值
* 输出 : 无
***********************************************************************/
void delay(uint ms)
{
uint x,y;
void RESET_887()
{
WRITE_DATA_887(4,23);//设定时
WRITE_DATA_887(2,59);//设定分
WRITE_DATA_887(0,55);//设定秒
WRITE_DATA_887(9,0x0a);//设定年
WRITE_DATA_887(8,0x0c);//设定月
* 名称 : display()
* 功能 : 4位数码管的显示函数
* 输入 : 显示值,最大值为9999
* 输出 : 无
***********************************************************************/
void display(uint a)
for(x=0;x<ms;x++)
{
for(y=0;y<1141;y++);
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
可读性非常好的MODBUS源代码(1)为了加快发送采用了:数据空中断(2)为了保证最后一个字节能够发送到上位机采用了:发送完成中断#include <iom128v.h>#include <macros.h>#define _USART1_H#include "DMS2000.h"const UCHAR auchCRCHi[] = {0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,0x80, 0x41, 0x00, 0xC1, 0x81, 0x40};const UCHAR auchCRCLo[] = {0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,0x43, 0x83, 0x41, 0x81, 0x80, 0x40};BOOL volatile USART1_send_mark = FALSE;UCHAR volatile USART1_sendPosi = 0;SHORT volatile USART1_receCount = 0;UCHAR volatile USART1_receTimeOut = 0;UCHAR volatile USART1_checkoutError = 0;UCHAR volatile USART1_sendCount = 0;UCHAR USART1_ch_type = 0;UCHAR USART1_set_number = 0;UCHAR USART1_send_buffer[MSCOMM_BUFFER_LENGTH]; UCHAR USART1_mscomm_buffer[MSCOMM_BUFFER_LENGTH];USHORT CRC16(UCHAR *puchMsg, USHORT usDataLen){UCHAR uchCRCHi = 0xFF;UCHAR uchCRCLo = 0xFF;ULONG uIndex;while (usDataLen--){uIndex = uchCRCHi ^ *puchMsg++;uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex];uchCRCLo = auchCRCLo[uIndex];}return (uchCRCHi << 8 | uchCRCLo);}void USART1_Init(SHORT MSCOMM_baud){UCHAR me_STOP = (UCHAR)(MSCOMM_baud & 0x01); UCHAR me_UPM = (UCHAR)(MSCOMM_baud & 0x06) >> 0x01; UCHAR me_Baud = (UCHAR)(MSCOMM_baud & 0x38) >> 0x03;UCSR1B = 0x00;UCSR1A = 0x00;UCSR1C = (1 << UCSZ10) | (1 << UCSZ11);switch (me_STOP){case 0:UCSR1C |= (0 << USBS1);break;case 1:UCSR1C |= (1 << USBS1);break;}switch (me_UPM){case 0:case 1:UCSR1C |= ((0 << UPM11) | ( 0 << UPM10));break;case 2:UCSR1C |= ((1 << UPM11) | ( 0 << UPM10));break;case 3:UCSR1C |= ((1 << UPM11) | ( 1 << UPM10));break;}switch (me_Baud){case 0:UBRR1L = 0x3F;UBRR1H = 0x02;break;case 1:UBRR1L = 0x1F;UBRR1H = 0x01;break;case 2:UBRR1L = 0x8F;UBRR1H = 0x00;break;case 3:UBRR1L = 0x47;UBRR1H = 0x00;break;case 4:UBRR1L = 0x23;UBRR1H = 0x00;break;case 5:UBRR1L = 0x11;UBRR1H = 0x00;break;case 6:UBRR1L = 0x0B;UBRR1H = 0x00;break;default:UBRR1L = 0x05;UBRR1H = 0x00;break;}UCSR1B = (1 << RXEN1) | (1 << RXCIE1) | (1 << TXEN1);}BOOL USART1_CoilRegistersAddr(SHORT startAddr,SHORT registerAmount) {if (registerAmount >= 1 && registerAmount <= 2000){if (startAddr >= 0 && startAddr <= 4){if ((startAddr + registerAmount - 1) <= 4)return (TRUE);}}return (FALSE);}void USART1_GetCoilVal(SHORT *tempData,SHORT tempAddr){switch (tempAddr){case 0:*tempData = 0;break;}}void USART1_SetCoilVal(SHORT OnOff,SHORT tempAddr){}BOOL USART1_DiscreteRegistersAddr(SHORT startAddr,SHORT registerAmount) {if (registerAmount >= 1 && registerAmount <= 2000){if (startAddr >= 0 && startAddr <= 7){if ((startAddr + registerAmount - 1) <= 7)return (TRUE);}}return (FALSE);}void USART1_GetDiscreteVal(SHORT *tempData,SHORT tempAddr){switch (tempAddr){case 0:*tempData = 0;break;}}BOOL USART1_InputRegisterAddr(SHORT startAddr,SHORT registerAmount)if (registerAmount >= 1 && registerAmount <= 125){if (startAddr >= 0 && startAddr <= 7){if ((startAddr + registerAmount - 1) <= 7)return (TRUE);}}return (FALSE);}void USART1_GetInputRegisterVal(SHORT *tempData,SHORT tempAddr){switch (tempAddr){case 0:*tempData = 0;break;}}BOOL USART1_HoldingRegisterAddr(SHORT startAddr,SHORT registerAmount,UCHAR *set_number) {if (registerAmount >= 1 && registerAmount <= 125){if (startAddr >= 0 && startAddr < BUFFER_LENGTH){if ((startAddr + registerAmount - 1) < BUFFER_LENGTH){*set_number = startAddr + 1;return (TRUE);}}}return (FALSE);}void USART1_GetHoldingRegisterVal(SHORT *tempData,UCHAR set_number){}BOOL USART1_SetHoldingRegisterVal(SHORT tempData,SHORT tempAddr) {return (FALSE);}void USART1_Time_Proc(void){if (USART1_receTimeOut > 0){USART1_receTimeOut--;if (USART1_receTimeOut == 0 && USART1_receCount > 0){USART1_receCount = 0;USART1_checkoutError = 0;if (!USART1_send_mark)RS485_RECIVE();}}}void USART1_Begin_Send(void){RS485_SEND();NOP(); // --------|NOP(); // |NOP(); // |-----------等待总线释放NOP(); // |NOP(); // --------|NOP(); // --------|NOP(); // |NOP(); // |-----------等待总线释放NOP(); // |NOP(); // --------|USART1_send_mark = TRUE;USART1_sendPosi = 0;UCSR1B |= BIT(5);}void USART1_MODBUS_Error(UCHAR error_code){USHORT crcData;USART1_send_buffer[0] = USART1_mscomm_buffer[0];USART1_send_buffer[1] = USART1_mscomm_buffer[1] | 0x80;USART1_send_buffer[2] = error_code;crcData = CRC16(USART1_send_buffer,3);USART1_send_buffer[3] = crcData >> 8;USART1_send_buffer[4] = crcData & 0xff;USART1_sendCount = 5;USART1_Begin_Send();}void USART1_ReadCoilRegisters(void){UCHAR i,k;UCHAR byteCount;SHORT registerAmount;SHORT startAddr;SHORT tempAddr;SHORT tempData;USHORT crcData;startAddr = (SHORT)(USART1_mscomm_buffer[2] << 8) + (SHORT)USART1_mscomm_buffer[3]; registerAmount = (SHORT)(USART1_mscomm_buffer[4] << 8) + (SHORT)USART1_mscomm_buffer[5]; if (USART1_CoilRegistersAddr(startAddr,registerAmount)){tempAddr = startAddr;byteCount = registerAmount >> 0x03;if (registerAmount & 0x07)byteCount++;for (k = 0 ; k < byteCount ; k++){USART1_send_buffer[k + 3] = 0;for (i = 0 ; i < 8 ; i++){USART1_GetCoilVal(&tempData,tempAddr++);USART1_send_buffer[k + 3] |= (tempData << i);if (tempAddr >= startAddr + registerAmount)break;}USART1_send_buffer[0] = USART1_mscomm_buffer[0];USART1_send_buffer[1] = USART1_mscomm_buffer[1];USART1_send_buffer[2] = byteCount;byteCount += 3;crcData = CRC16(USART1_send_buffer,byteCount);USART1_send_buffer[byteCount] = crcData >> 8;byteCount++;USART1_send_buffer[byteCount] = crcData & 0xff;USART1_sendCount = byteCount + 1;USART1_Begin_Send();}elseUSART1_MODBUS_Error(2);}void USART1_ReadDiscreteRegisters(void){UCHAR i,k;UCHAR byteCount;SHORT registerAmount;SHORT startAddr;SHORT tempAddr;SHORT tempData;USHORT crcData;startAddr = (SHORT)(USART1_mscomm_buffer[2] << 8) + (SHORT)USART1_mscomm_buffer[3]; registerAmount = (SHORT)(USART1_mscomm_buffer[4] << 8) + (SHORT)USART1_mscomm_buffer[5]; if (USART1_DiscreteRegistersAddr(startAddr,registerAmount)){tempAddr = startAddr;byteCount = registerAmount >> 0x03;if (registerAmount & 0x07)byteCount++;for (k = 0 ; k < byteCount ; k++){USART1_send_buffer[k + 3] = 0;for (i = 0 ; i < 8 ; i++){USART1_GetDiscreteVal(&tempData,tempAddr++);USART1_send_buffer[k + 3] |= (tempData << i);if (tempAddr >= startAddr + registerAmount)break;}}USART1_send_buffer[0] = USART1_mscomm_buffer[0];USART1_send_buffer[1] = USART1_mscomm_buffer[1];USART1_send_buffer[2] = byteCount;byteCount += 3;crcData = CRC16(USART1_send_buffer,byteCount);USART1_send_buffer[byteCount] = crcData >> 8;byteCount++;USART1_send_buffer[byteCount] = crcData & 0xff;USART1_sendCount = byteCount + 1;USART1_Begin_Send();}elseUSART1_MODBUS_Error(2);}void USART1_ReadHoldingRegisters(void){UCHAR i;SHORT startAddr;SHORT registerAmount;SHORT byteCount;SHORT tempData;USHORT crcData;startAddr = (SHORT)(USART1_mscomm_buffer[2]<<8) + (SHORT)USART1_mscomm_buffer[3]; registerAmount = (SHORT)(USART1_mscomm_buffer[4]<<8) + (SHORT)USART1_mscomm_buffer[5]; if (USART1_HoldingRegisterAddr(startAddr,registerAmount,&USART1_set_number)){byteCount = registerAmount << 0x01;for (i = 0 ; i < registerAmount ; i++){USART1_GetHoldingRegisterVal(&tempData,USART1_set_number++);USART1_send_buffer[2*i+3] = tempData >> 8;USART1_send_buffer[2*i+4] = tempData & 0xff;}USART1_send_buffer[0] = USART1_mscomm_buffer[0];USART1_send_buffer[1] = USART1_mscomm_buffer[1];USART1_send_buffer[2] = byteCount;byteCount += 3;crcData = CRC16(USART1_send_buffer,byteCount);USART1_send_buffer[byteCount] = crcData >> 8;byteCount++;USART1_send_buffer[byteCount] = crcData & 0xff;USART1_sendCount = byteCount + 1;USART1_Begin_Send();}elseUSART1_MODBUS_Error(2);}void USART1_ReadInputRegisters(void){UCHAR i;SHORT startAddr;SHORT tempAddr;SHORT registerAmount;SHORT byteCount;SHORT tempData;USHORT crcData;startAddr = (SHORT)(USART1_mscomm_buffer[2]<<8) + (SHORT)USART1_mscomm_buffer[3]; registerAmount = (SHORT)(USART1_mscomm_buffer[4]<<8) + (SHORT)USART1_mscomm_buffer[5]; if (USART1_InputRegisterAddr(startAddr,registerAmount)){tempAddr = startAddr;byteCount = registerAmount << 0x01;for (i = 0 ; i < registerAmount ; i++){USART1_GetInputRegisterVal(&tempData,tempAddr++);USART1_send_buffer[2*i+3] = tempData >> 8;USART1_send_buffer[2*i+4] = tempData & 0xff;}USART1_send_buffer[0] = USART1_mscomm_buffer[0];USART1_send_buffer[1] = USART1_mscomm_buffer[1];USART1_send_buffer[2] = byteCount;byteCount += 3;crcData = CRC16(USART1_send_buffer,byteCount);USART1_send_buffer[byteCount] = crcData >> 8;byteCount++;USART1_send_buffer[byteCount] = crcData & 0xff;USART1_sendCount = byteCount + 1;USART1_Begin_Send();}elseUSART1_MODBUS_Error(2);}void USART1_ForceSingleCoil(void){UCHAR i;SHORT OnOff;SHORT startAddr;startAddr = (SHORT)(USART1_mscomm_buffer[2] << 8) + (SHORT)USART1_mscomm_buffer[3]; if (USART1_CoilRegistersAddr(startAddr,1)){OnOff = (SHORT)(USART1_mscomm_buffer[4] << 8) + (SHORT)USART1_mscomm_buffer[5]; switch (OnOff){case 0x00:USART1_SetCoilVal(0,startAddr);break;case 0xFF:USART1_SetCoilVal(1,startAddr);break;}if (USART1_mscomm_buffer[0] == module_addr){for (i = 0 ; i < 8 ; i++)USART1_send_buffer[i] = USART1_mscomm_buffer[i];USART1_sendCount = 8;USART1_Begin_Send();}}else if (USART1_mscomm_buffer[0] == module_addr)USART1_MODBUS_Error(2);}void USART1_PresetSingleHoldingRegister(void){UCHAR i;SHORT startAddr;SHORT tempData;startAddr = (SHORT)(USART1_mscomm_buffer[2]<<8) + (SHORT)USART1_mscomm_buffer[3];tempData = (SHORT)(USART1_mscomm_buffer[4]<<8) + (SHORT)USART1_mscomm_buffer[5];if (USART1_HoldingRegisterAddr(startAddr,1,&USART1_set_number)){if (USART1_mscomm_buffer[0] == module_addr){for (i = 0 ; i < 8 ; i++)USART1_send_buffer[i] = USART1_mscomm_buffer[i];USART1_sendCount = 8;USART1_Begin_Send();}if (USART1_SetHoldingRegisterVal(tempData,startAddr)){QUEUE_In_CRC16();EEPROM_START();}}else if (USART1_mscomm_buffer[0] == module_addr)USART1_MODBUS_Error(2);}void USART1_ForceMultipleCoil(void){UCHAR i,k;UCHAR byteCount;SHORT registerAmount;SHORT startAddr;SHORT tempAddr;SHORT OnOff;USHORT crcData;startAddr = (SHORT)(USART1_mscomm_buffer[2]<<8) + (SHORT)USART1_mscomm_buffer[3]; registerAmount = (SHORT)(USART1_mscomm_buffer[4] << 8) + (SHORT)USART1_mscomm_buffer[5]; if (USART1_CoilRegistersAddr(startAddr,registerAmount)){tempAddr = startAddr;byteCount = (SHORT)USART1_mscomm_buffer[6];if (USART1_mscomm_buffer[0] == module_addr){for (i = 0 ; i < 6 ; i++)USART1_send_buffer[i] = USART1_mscomm_buffer[i];crcData = CRC16(USART1_send_buffer,6);USART1_send_buffer[6] = crcData >> 8;USART1_send_buffer[7] = crcData & 0xff;USART1_sendCount = 8;USART1_Begin_Send();}for (k = 0 ; k < byteCount ; k++){for (i = 0 ; i < 8 ; i++){OnOff = USART1_mscomm_buffer[k+7] >> i;if (OnOff & 0x01)USART1_SetCoilVal(1,tempAddr++);elseUSART1_SetCoilVal(0,tempAddr++);if (tempAddr >= startAddr + registerAmount)break;}}}else if (USART1_mscomm_buffer[0] == module_addr)USART1_MODBUS_Error(2);}void USART1_PresetMultipleHoldingRegisters(void){UCHAR i;SHORT registerAmount;SHORT startAddr;SHORT tempData;USHORT crcData;BOOL Enable = FALSE;startAddr = (SHORT)(USART1_mscomm_buffer[2]<<8) + (SHORT)USART1_mscomm_buffer[3]; registerAmount = (SHORT)(USART1_mscomm_buffer[4]<<8) + (SHORT)USART1_mscomm_buffer[5]; if (USART1_HoldingRegisterAddr(startAddr,registerAmount,&USART1_set_number)){if (USART1_mscomm_buffer[0] == module_addr){for (i = 0 ; i < 6 ; i++)USART1_send_buffer[i] = USART1_mscomm_buffer[i];crcData = CRC16(USART1_send_buffer,6);USART1_send_buffer[6] = crcData >> 8;USART1_send_buffer[7] = crcData & 0xff;USART1_sendCount = 8;USART1_Begin_Send();for (i = 0 ; i < registerAmount ; i++){tempData = (SHORT)(USART1_mscomm_buffer[i*2+7]<<8) + (SHORT)USART1_mscomm_buffer[i*2+8]; if (USART1_SetHoldingRegisterVal(tempData,startAddr++))Enable = TRUE;}if (Enable){QUEUE_In_CRC16();EEPROM_START();}}elseUSART1_MODBUS_Error(2);}void USART1_Modbus_Analyze(void){SHORT tempData;USHORT crcData;if (USART1_receCount > 5){switch (USART1_mscomm_buffer[1]){case 1:if (USART1_receCount >= 8){UCSR1B &= ~BIT(7);if (USART1_mscomm_buffer[0] == module_addr && USART1_checkoutError == 0){crcData = CRC16(USART1_mscomm_buffer,6);if (crcData == (USHORT)(USART1_mscomm_buffer[6] << 8) + (USHORT)USART1_mscomm_buffer[7]) USART1_ReadCoilRegisters();}USART1_receCount = 0;USART1_checkoutError = 0;UCSR1B |= BIT(7);}break;case 2:if (USART1_receCount >= 8)UCSR1B &= ~BIT(7);if (USART1_mscomm_buffer[0] == module_addr && USART1_checkoutError == 0){crcData = CRC16(USART1_mscomm_buffer,6);if (crcData == (USHORT)(USART1_mscomm_buffer[6] << 8) + (USHORT)USART1_mscomm_buffer[7]) USART1_ReadDiscreteRegisters();}USART1_receCount = 0;USART1_checkoutError = 0;UCSR1B |= BIT(7);}break;case 3:if (USART1_receCount >= 8){UCSR1B &= ~BIT(7);if (USART1_mscomm_buffer[0] == module_addr && USART1_checkoutError == 0){crcData = CRC16(USART1_mscomm_buffer,6);if (crcData == (USHORT)(USART1_mscomm_buffer[6] << 8) + (USHORT)USART1_mscomm_buffer[7]) USART1_ReadHoldingRegisters();}USART1_receCount = 0;USART1_checkoutError = 0;UCSR1B |= BIT(7);}break;case 4:if (USART1_receCount >= 8){UCSR1B &= ~BIT(7);if (USART1_mscomm_buffer[0] == module_addr && USART1_checkoutError == 0){crcData = CRC16(USART1_mscomm_buffer,6);if (crcData == (USHORT)(USART1_mscomm_buffer[6] << 8) + (USHORT)USART1_mscomm_buffer[7]) USART1_ReadInputRegisters();}USART1_receCount = 0;USART1_checkoutError = 0;UCSR1B |= BIT(7);}break;case 5:if (USART1_receCount >= 8){UCSR1B &= ~BIT(7);if ((USART1_mscomm_buffer[0] == module_addr || USART1_mscomm_buffer[0] == 0) && USART1_checkout Error == 0){crcData = CRC16(USART1_mscomm_buffer,6);if (crcData == (USHORT)(USART1_mscomm_buffer[6] << 8) + (USHORT)USART1_mscomm_buffer[7]) USART1_ForceSingleCoil();}USART1_receCount = 0;USART1_checkoutError = 0;UCSR1B |= BIT(7);}break;case 6:if (USART1_receCount >= 8){UCSR1B &= ~BIT(7);if ((USART1_mscomm_buffer[0] == module_addr || USART1_mscomm_buffer[0] == 0) && USART1_checkout Error == 0){crcData = CRC16(USART1_mscomm_buffer,6);if (crcData == (USHORT)(USART1_mscomm_buffer[6] << 8) + (USHORT)USART1_mscomm_buffer[7]) USART1_PresetSingleHoldingRegister();}USART1_receCount = 0;USART1_checkoutError = 0;UCSR1B |= BIT(7);}break;case 15:if ((USART1_mscomm_buffer[0] == module_addr || USART1_mscomm_buffer[0] == 0) && USART1_checkout Error == 0){tempData = (SHORT)(USART1_mscomm_buffer[6]);tempData += 9;if (USART1_receCount >= tempData && USART1_receCount < MSCOMM_BUFFER_LENGTH){UCSR1B &= ~BIT(7);crcData = CRC16(USART1_mscomm_buffer,tempData - 2);if (crcData == (USHORT)(USART1_mscomm_buffer[tempData - 2] << 8) + (USHORT)USART1_mscomm_buff er[tempData - 1])USART1_ForceMultipleCoil();USART1_receCount = 0;USART1_checkoutError = 0;UCSR1B |= BIT(7);}}break;case 16:if ((USART1_mscomm_buffer[0] == module_addr || USART1_mscomm_buffer[0] == 0) && USART1_checkout Error == 0){tempData = (SHORT)(USART1_mscomm_buffer[4]<<8) + (SHORT)USART1_mscomm_buffer[5];tempData <<= 0x01;tempData += 9;if (USART1_receCount >= tempData && USART1_receCount < MSCOMM_BUFFER_LENGTH){UCSR1B &= ~BIT(7);crcData = CRC16(USART1_mscomm_buffer,tempData - 2);if (crcData == (USHORT)(USART1_mscomm_buffer[tempData - 2] << 8) + (USHORT)USART1_mscomm_buff er[tempData - 1])USART1_PresetMultipleHoldingRegisters();USART1_receCount = 0;USART1_checkoutError = 0;UCSR1B |= BIT(7);}}break;}}}/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 可靠地判断帧结束,防止通信停滞/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 利用单独的软件定时器,来判断一帧接收报文结束,可以防止若报文接收不完整,该帧通信任务无法结束而影响下一帧的接收。