基于AVRmega128的modbus程序
- 格式:doc
- 大小:47.00 KB
- 文档页数:20
#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协议的方法有幸做了个项目,其中使用到了单片机和上位机通讯的程序,上位机用组态实现功能,探索了些方法,写出来和大家分享一下,这些知识本不是什么秘密,本人参考了许多资料,自己整合了一下。
每种程序都是算法多样,最终功能实现就行。
大家做单片机串口通讯时是不是总想有一种以不变应万变的思想,就是在底层单片机硬件和软件不变的情况下,去适应任何上位机软件系统,当然可以实现,这就需要用到标准的通讯协议了,以下我就和大家分享一下我做的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串口通讯测试程序/********************************************************说明: 需要串口调协助实验(波特率设为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单片机调试与设置一、单片机型号为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单片机mega128例程大全//16超声波LED显示#include //PA0接控制引脚PA7接接收引脚#include #define chao 100longint time=0;void delay(long int z){inti,j;for(i=0;i<z;i++)< bdsfid="72" p=""></z;i++)<> for(j=0;j<100;j++);}void main(){int o=0;DDRD=0xff;DDRA=0x0f;TCNT1H=0x00;TCNT1L=0x00;while(1){PORTA=0x0f;delay(1);PORTA=0x00;while((PINA&0x80)==0x00); TCCR1B=0x03; while((PINA&0x80)==0x80); TCCR1B=0x00;time=TCNT1H*256+TCNT1L; TCNT1H=0x00; TCNT1L=0x00;if(time<chao)< bdsfid="92" p=""></chao)<> {if(time<chao)< bdsfid="95" p=""></chao)<>{o=500;while(o--)PORTD=0x04;}}if(time>chao){if(time>chao){o=500;while(o--)PORTD=0x08;}}}}//AD#include#include#define unint unsigned int#define unchar unsigned char#pragma data:codeconst table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d, 0x07, 0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};unint mega128_ad(){unintaddata;DDRF&=~BIT(0);ADMUX=0;ADCSRA=0X80;ADCSRA|=BIT(ADSC);while(!(ADCSRA&(BIT(ADIF)))); addata=ADCL;addata=addata+ADCH*256; returnaddata;}void show(count){unchar temp1,temp2,temp3,temp4; temp1=count/1000;temp2=(count%1000)/100;temp3=(count%100)/10;temp4=count%10;HC_595_OUT(table[temp4]); DDRB|=(1<<4);PORTB|=(1<<4);delay(10);DDRB|=(1<<4);PORTB&=~(1<<4);HC_595_OUT(table[temp3]); DDRB|=(1<<5);PORTB|=(1<<5);delay(10);DDRB|=(1<<5);PORTB&=~(1<<5);HC_595_OUT(table[temp2]); DDRB|=(1<<6);delay(10);DDRB|=(1<<6);PORTB&=~(1<<6);HC_595_OUT(table[temp1]);DDRB|=(1<<7);PORTB|=(1<<7);delay(10);DDRB|=(1<<7);PORTB&=~(1<<7);}void HC_595_OUT(count){PORTB&=~(1<<0);SPDR =count ;while(!(SPSR & (1<<spif)));< bdsfid="173" p=""></spif)));<> delay(10);PORTB|=(1<<0);}void delay(z){unintx,y;for(x=0;x<z;x++)< bdsfid="181" p=""></z;x++)<>for(y=0;y<200;y++);}void main(){unintcount,chl;DDRC |= (1<<7);PORTC &= (1<<7);DDRB |= (1<<2)|(1<<1)|(1<<0);SPCR = (1<<spe)|(1<<mstr)|(1<<spr0)|(1<<spr1);< bdsfid="192" p=""></spe)|(1<<mstr)|(1<<spr0)|(1<<spr1);<> while(1){count=mega128_ad();//用参数代替老是出问题,这一点需要再次认知考虑/*for(i=0;i<4;i++){ad[3-i]=shuzhi%10;shuzhi=shuzhi/10;}*/show(count);}}//ADC#include#include#define unint unsigned int#define unchar unsigned char#pragma data:codeconst table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d, 0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};unint mega128_ad(){unintaddata;DDRF&=~BIT(0);PORTF&=~BIT(0);ADMUX=0;ADCSRA=0X80;ADCSRA|=BIT(ADSC);while(!(ADCSRA&(BIT(ADIF)))); addata=ADCL; addata=addata+ADCH*256; returnaddata; }void show(count){unchar temp1,temp2,temp3,temp4;temp1=count/1000;temp2=(count%1000)/100;temp3=(count%100)/10;temp4=count%10;HC_595_OUT(table[temp4]);DDRB|=(1<<4);PORTB|=(1<<4);delay(10);DDRB|=(1<<4);PORTB&=~(1<<4);HC_595_OUT(table[temp3]);DDRB|=(1<<5);PORTB|=(1<<5);delay(10);DDRB|=(1<<5);PORTB&=~(1<<5);HC_595_OUT(table[temp2]);DDRB|=(1<<6);PORTB|=(1<<6);delay(10);DDRB|=(1<<6);PORTB&=~(1<<6);HC_595_OUT(table[temp1]);DDRB|=(1<<7);PORTB|=(1<<7); delay(10);DDRB|=(1<<7);PORTB&=~(1<<7);}void HC_595_OUT(count) {PORTB&=~(1<<0);SPDR =count ;while(!(SPSR & (1<<spif)));< bdsfid="260" p=""></spif)));<> delay(10);PORTB|=(1<<0);}void delay(z){unintx,y;for(x=0;x<z;x++)< bdsfid="268" p=""></z;x++)<>for(y=0;y<200;y++);}void main()unintcount,chl;DDRC |= (1<<7);PORTC &= (1<<7);PORTB = 0x0F;DDRB |= (1<<2)|(1<<1)|(1<<0);SPCR = (1<<spe)|(1<<mstr)|(1<<spr0)|(1<<spr1);< bdsfid="278" p=""></spe)|(1<<mstr)|(1<<spr0)|(1<<spr1);<> while(1){count=mega128_ad();//用参数代替老是出问题,这一点需要再次认知考虑/*for(i=0;i<4;i++){ad[3-i]=shuzhi%10;shuzhi=shuzhi/10;}*/show(count);}}//CTC//该程序并未在示波器上测试,在仿真软件上仿真时只有PB5上有方波信号出现#include#include#define uchar unsigned char#define uint unsigned intvoid main(){DDRB|=0X60;TCCR1A=0X50;TCCR1B=0X09;OCR1A=0X7CF;}//D口矩阵键盘检测#include "config.h"#include#include#define unint unsigned int#define unchar unsigned charconst unsigned char Seg7_Data[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,0x00};unchar temp1,temp2,temp3,temp4; unintdata,z;void HC_595_init(){DDRC=0x80;PORTC=0x00;PORTB=0x0F;DDRB=0x07;SPCR =0x53;}void Seg7_Led_display(unint data) {unchar temp1,temp2,temp3,temp4;temp1=data/1000;temp2=(data%1000)/100;temp3=(data%100)/10;temp4=data%10;HC_595_OUT(Seg7_Data[temp4]);PORTB|=(1<<4);delay(20);PORTB&=~(1<<4);HC_595_OUT(Seg7_Data[temp3]);PORTB|=(1<<5);delay(20);PORTB&=~(1<<5);HC_595_OUT(Seg7_Data[temp2]); PORTB|=(1<<6); delay(20);PORTB&=~(1<<6);HC_595_OUT(Seg7_Data[temp1]);PORTB|=(1<<7);delay(20);PORTB&=~(1<<7);}void HC_595_OUT(unchar data){PORTB=0x06;SPDR =data ;while(SPSR==0);delay(10);PORTB=0x01;}void delay(unint z){uninti,j;for(i=0;i<z;i++)< bdsfid="360" p=""></z;i++)<> for(j=0;j<100;j++);}void delay_1us(void) //1us延时函{asm("nop");}void delay_nus(unsigned int n) //N us延时函数{ unsignedint i=0;for (i=0;i<n;i++)< bdsfid="370" p=""></n;i++)<> delay_1us();}void delay_1ms(void) //1ms延时函数{unsignedint i;for (i=0;i<1140;i++);}void delay_nms(unsigned int n) //N ms延时函数{unsignedint i=0;for (i=0;i<n;i++)< bdsfid="382" p=""></n;i++)<> delay_1ms();voidBuzz_init(void){DDRG |= (1<<4);PORTG &=~ (1<<4);}void Beep(unsigned intH_time,unsignedintL_time) { PORTG |= (1<<4);delay_nms(H_time);PORTG &=~ (1<<4);delay_nms(L_time);}intkey_press(void){int k;delay_nms(5);PORTD=0x01;delay_nms(5);if((PIND&0xF0)!=0x00){delay_nms(10);if((PIND&0xF0)!=0x00){if(PIND==0x11) {Beep(100,50); PORTA=0x1F;k=1;}else if(PIND==0x21) { Beep(100,50); PORTA=0xFD; k=2;}else if(PIND==0x41) { Beep(100,50); PORTA=0xFB; k=3;}else if(PIND==0x81) { Beep(100,50);。
科技与创新┃Science and Technology&Innovation ·90·2023年第21期文章编号:2095-6835(2023)21-0090-03基于MEGA128单片机的数控开关电源的设计卢启硕,秦琛(国网淮南市潘集区供电公司,安徽淮南232082)摘要:首先将交流电经过AD-DC整流单元电路转化为稳定直流电,滤波后经过DC-AC逆变电路转化为稳定的交流电,通过高频变压器后,接入整流单元滤波系统以获得所需要的直流电,通过反馈回路接入高频变压器的输出部分,再通过UC3844的高占空比获得一定的输出电流,并选用MEGA128单片微型机为主控制器件,设计的主要目的为控制高频变压器。
关键词:逆变电路;高频变压器;UC3844;数控开关电源中图分类号:TN86文献标志码:A DOI:10.15913/ki.kjycx.2023.21.026开关式电源技术与之前的技术相比有了很大提高,脉冲宽度调制(Pulse Width Modulation,PWM技术)得到广泛推广[1]。
使用20kHz的调制信号,可以使开关式电源的效率达到65%~75%,与之相比,线性电源的效率仅为30%~40%。
开关电源的工作原理比较简单,首先通过转换将220V的交流电源转化为高质量的直流电,再将得到的高品质的直流电转化为频率较高的交流电,最后整流得到直流电。
反馈电路采集输出电压,然后送到单片机将模拟量转变为数字量,处理之后调节输出的PWM脉冲占空比,经过以上处理变换以后才能得到与要求相符的直流电压,该直流电压的纹波和稳定性得到很大的改善[2]。
本文利用MEGA128单片机作为处理器,来设计输出电压可调的数字开关电源。
1硬件电路设计1.1主电路开关式电源的原理图如图1所示。
按照前文所述的步骤得到适合的直流电后,向单端反激式变换电路供电[3]。
选用功率MOSFET(金属氧化物半导体场效应晶体管)作为功率开关管,UC3844控制PWM脉冲的占空比,主要原理是UC3844控制MOSFET功率开关管的PWM的占空比,从而达到对输出电压的稳定控制。
可读性非常好的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;}}}/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 可靠地判断帧结束,防止通信停滞/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 利用单独的软件定时器,来判断一帧接收报文结束,可以防止若报文接收不完整,该帧通信任务无法结束而影响下一帧的接收。