基于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++);
AVR单片机mega128例程大全
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);。
基于MEGA128_单片机的数控开关电源的设计
科技与创新┃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的占空比,从而达到对输出电压的稳定控制。
基于ATmega128的测控系统的Modbus通信
单片机 AT meg a128 是 AT M EL 公司的一款基 于增强精简指令集 RISC 结构的 8 位微控制器 。 它 运用 H arva rd 结构 , 在前一条指令执行时就取出现 行指令 , 再以一个周期执行指令[ 2] 。 它拥有大容量 的存储器及各种接口 , 其中与实现 Modbus 通信相 关的接口是一高度灵活的串行通信设备即全双工通 用同步 /异步串行收发模块 USA RT , 分为时钟发生 器 、数据发送器和接收器 3 部分(见图 2)。 控制寄 存器为所有模块共享 。
大的优点来弥补下位机相对地速度慢 、容量小等不 足 , 从而更趋完善 。
5 结 语
M odbus 串行通信协议一般多用在 16 或 32 位 P LC 通信模块中[ 4] , 但本文经巧妙的程序处理后在 8 位 AV R 单片机中也实现了 Mo dbus 协议(Mo dbus RT U 模 式)及与上 位机组态 软件 的实时 通信 。 这无疑使该微 机监控系统存储数据的 能力大大提 高 , 现场测试的危险性减小 , 更重要的是测试仪不再 是一台孤立的仪器 , 不用开发任何驱动程序而只通 过简单的组态即可方便地接入任何支持 M odbus 协 议的组态软件中 , 从而有效克服了常见的“自动化孤 岛”现象 。本文所用的设计思想和方法对类似下位 机系统有普遍的启发和借鉴意义 。
0 引 言
最初由莫迪康(M odicon)公司制定的 M odbus 协议现已逐渐发展成为流行的 开放性工业标 准之 一 , 且 被 国 内 外知 名 组 态 软 件 如 iF IX 、组 态 王 、 MCGS 等支持 。 本文所涉及的 下位机系统是 采用 AT meg a128 单片机开发的 、用来测试及预测高压开 关相关机械特性的高压开关测试仪 。高压开关的工 作环境一般较危险 , 不适于近距离采集现场数据 , 而 Mo dbus 协议作为普遍通用的串行通信协议 , 恰可 实现远距离传输数据 。 故本文在 A T mega128 单片 机中开发了 Mo dbus 通信接口模块 , 以与无需再开 发任何驱动程序的上位机组态软件通信 。
史上最全的AVR128例程
自己学avr单片机已经有相当一段时间了,一开始用的是atmega128,觉得不是很好用。
于是自己去买了一块16L的芯片,觉得还行。
一开始用的是ICC A VR,应为它用起来比较简单,不像winavr那样,要写个Makefie,比较的麻烦,但icc avr的缺点是太过于简陋,调试程序时,感觉不是很好。
后来经同学介绍,用起了winavr,其实也是比较的简单,只不过要加一个makefile而已,其实makefile 可以用软件自带的组建自动生成,只需修改几个参数就可以用。
后来又用起了code vision avr,虽然不太习惯,也谈不上不好用.需要注意的是,三个不同的软件所带的同文件不一样。
icc avr 是iom128v.h(姑且以128为例),winavr是avr/io.h,不过makefile中要设置芯片为atmega128.而cvavr则是mega128.h。
记得一开始的时候,我对这些不同的同文件不是很理解,是从一个学长那里了解到,才弄明白的。
其实前两个软件只需把头文件稍微改一下基本上可以通用。
而最后一个软件的中断的写法似乎不太一样,因而和钱两个软件的兼容性是最差的。
总体说winavr给人的感觉是比较专业1、流水灯/*硬件环境:atmega128开发板软件环境:CodeVisionA VR-C*/#include <mega128.h>#define uchar unsigned char#define uint unsigned intuchar cnt;void timer1_init(){TCCR1B=0X00; //先停止定时器1TCNT1H=0XF0; //设定定时器初值TCNT1L=0XBE;TCCR1A=0X00; //启动定时器1TCCR1B=0X05; //使用1024分频}interrupt [TIM1_OVF] void timer1_ovf_isr(void){TCNT1H=0XF0; //重载定时器初值TCNT1L=0XBE;DDRE|=1<<2;PORTE|=1<<2;DDRA=0xff;PORTA=cnt; //输出led的值到端口Bcnt++;if(cnt==255)cnt=0;}void main(){//DDRB=0XFF;SREG|=0X80;TIMSK=0X04;timer1_init();while(1){;}}2、AD转换+数码管显示/***************************************************************************//*ADC测试程序*//*目标器件:ATmega128 *//*晶振:RC 8MHZ *//*编译环境:ICCA VR 7.13A *//*E-Mail:**********************//*时间:2010年11月13日*///Aref接A VCC(+5V),采用Aref作参考电压/*用数码管显示AD转换的结果*//***************************************************************************//*********************************包含头文件********************************/#include <iom128v.h>#include <macros.h>/********************************数码管段码表*******************************/ extern const unsigned char tab[]={0x3f,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};/*********************************全局变量**********************************/ unsigned int adc_rel=0;/****************************************************************************函数功能:ADC初始化函数入口参数:出口参数:****************************************************************************/ void adc_init(void){DDRF&=0XFE; //PORTF0设置为输入,即作为ADC0口输入模拟电压PORTF&=0XFE; //PORTF0设置为输入低电平ADCSRA=0x00; //关ADCADMUX = 0X00; //采用Aref作为参考电压,ADC0单端输入,右对齐ACSR=(1<<ACD);ADCSRA = (1<<ADEN)|(1<<ADSC)|(1<<ADATE)|(1<<ADIE)|(1<<ADPS2)|(1<<ADPS1);//ADEN,启动ADC;ADSC,ADC开始转换;ADIE,ADC中断使能;ADPSx,设置分频因子64}/**************************************************************************** 函数功能:ADC中断函数入口参数:出口参数:****************************************************************************/ #pragma interrupt_handler adc_isr:iv_ADCvoid adc_isr(void){//int data_h,data_l;//data_l=ADCL;//data_h=ADCH;ADCSRA = 0x00;ADCSRA = (1<<ADEN)|(1<<ADSC)|(1<<ADIE);adc_rel=ADC;/*if(adc_rel>0x1ff){PORTA|=1<<2;}elsePORTA&=~(1<<2);*/}/**************************************************************************** 函数功能:延时子程序入口参数:出口参数:****************************************************************************/ void delay(void){int i;for(i=0;i<1800;i++);}/**************************************************************************** 函数功能:显示子程序入口参数:k出口参数:****************************************************************************/ void display(unsigned int k)//发光二极管显示初始化{DDRE|=1<<2;PORTE|=1<<2;DDRA=0XFF;PORTA=k;}#define SS 0#define SCK 1#define MOSI 2#define MISO 3#define SS_H() PORTB|=(1<<SS)#define SS_L() PORTB&=~(1<<SS)#define led0_en() {DDRB|=1<<4;PORTB|=(1<<4);} //开第一个数码管的位选#define led0_dis() {DDRB|=1<<4;PORTB&=~(1<<4);} //关第一个数码管的位选#define led1_en() {DDRB|=1<<5;PORTB|=(1<<5);}#define led1_dis() {DDRB|=1<<5;PORTB&=~(1<<5);}#define led2_en() {DDRB|=1<<6;PORTB|=(1<<6);}#define led2_dis() {DDRB|=1<<6;PORTB&=~(1<<6);}#define led3_en() {DDRB|=1<<7;PORTB|=(1<<7);}#define led3_dis() {DDRB|=1<<7;PORTB&=~(1<<7);}#define OE 7#define point 3#define dp 7#include <iom128v.h>#include <macros.h>const unsigned char table[]={0x3F,0x06,0x5B,0x4F,0x66, //0,1,2,3,40x6D,0x7D,0x07,0x7F,0x6F, //5,6,7,8,90x77,0x7C,0x39,0x5E,0x79,0x71,0x00}; //a,b,c,d,e,fvolatile unsigned char led_buffer[4];void delay_1us(void) //1us延时函数{asm("nop");}void delay_nus(unsigned int n) //N us延时函数{unsigned int i=0;for (i=0;i<n;i++)delay_1us();}void delay_1ms(void) //1ms延时函数{unsigned int i;for (i=0;i<1140;i++);}void delay_nms(unsigned int n) //N ms延时函数{unsigned int i=0;for (i=0;i<n;i++)delay_1ms();}/*完成spi的初始化*/void spi_init(void){DDRB |= (1<<MOSI)|(1<<SCK)|(1<<SS);//设置MOSI,SCK输出SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0)|(1<<SPR1);//使能SPI,主机模式}/*spi主机传送数据*/void SPI_MasterTransmit(char Data){/* 启动数据传输*/SPDR = Data;/* 等待传输结束*/while(!(SPSR & (1<<SPIF)));}/*完成对HC595的初始化*/void HC_595_init(void){DDRC |= (1<<OE); //设置PORTC7为输出PORTC &= (1<<OE); //输出高电平,使能595PORTB = 0x0F; //同时打开四个数码管的位选spi_init();led_buffer[0]=16; //初始化数码管段码led_buffer[1]=16;led_buffer[2]=16;led_buffer[3]=16;}/*HC595完成传送数据*/void HC_595_OUT(unsigned char data){SS_L();SPI_MasterTransmit(data);SS_H();}void leddis_update(void){/*最低位数码管,第四个数码管*/if(point==0)HC_595_OUT(table[led_buffer[3]]|(1<<dp));elseHC_595_OUT(table[led_buffer[3]]);led0_en();delay_nus(60);led0_dis();if(point==1)HC_595_OUT(table[led_buffer[2]]|(1<<dp));elseHC_595_OUT(table[led_buffer[2]]);led1_en();delay_nus(60);led1_dis();if(point==2)HC_595_OUT(table[led_buffer[1]]|(1<<dp));elseHC_595_OUT(table[led_buffer[1]]);led2_en();delay_nus(60);led2_dis();/*最高位数码管,第一个数码管*/if(point==3)HC_595_OUT(table[led_buffer[0]]|(1<<dp));elseHC_595_OUT(table[led_buffer[0]]);led3_en();delay_nus(60);led3_dis();}void display_led(unsigned int data){if(data>9999){HC_595_OUT(0xFF);//当计数大于9999时,四个数码管同时输出8 PORTB|=((1<<4)|(1<<5)|(1<<6)|(1<<7));}else if(data>999){led_buffer[0]=data/1000;led_buffer[1]=(data%1000)/100;led_buffer[2]=(data%100)/10;led_buffer[3]=data%10;leddis_update();}else if(data>99){led_buffer[0]=data/1000; //关闭最高位的那个数码管led_buffer[1]=(data%1000)/100;led_buffer[2]=(data%100)/10;led_buffer[3]=data%10;leddis_update();}else if(data>9){led_buffer[0]=data/1000;led_buffer[1]=16;led_buffer[2]=(data%100)/10;led_buffer[3]=data%10;leddis_update();}else{led_buffer[0]=data/1000;led_buffer[1]=16;led_buffer[2]=16;led_buffer[3]=data%10;leddis_update();}}volatile unsigned int countnum=0;void timer1_init(void){TCCR1B = 0x00; //stopTCNT1H = 0x8F; //setupTCNT1L = 0x81;OCR1AH = 0x70;OCR1AL = 0x7F;OCR1BH = 0x70;OCR1BL = 0x7F;OCR1CH = 0x70;OCR1CL = 0x7F;ICR1H = 0x70;ICR1L = 0x7F;TCCR1A = 0x00;TCCR1B = 0x04; //start Timer}#pragma interrupt_handler timer1_ovf_isr:15void timer1_ovf_isr(void){TCNT1H = 0x8F; //reload counter high valueTCNT1L = 0x81; //reload counter low valuecountnum++;if(countnum>9999) countnum=0;}void init_devices(void){CLI(); //disable all interruptstimer1_init();TIMSK = 0x04; //timer interrupt sourcesSEI(); //re-enable interrupts}/**************************************************************************** 函数功能:主程序入口参数:出口参数:****************************************************************************/ void main(void){init_devices();HC_595_init();adc_init();SEI();//开全局中断变量display(0);while(1){delay();display_led(adc_rel/1024.0*5*1000);}}3、对EEPROM进行读写操作/************************************************文件:main.c用途:注意:内部8M晶振************************************************/#include "config.h"/*向EEPROM里面写入数据输入量:地址,数据*/void EEPROM_write(unsigned int uiAddress,unsigned char ucData) {while(EECR&(1<<EEWE)); //等待上一次写操作结束EEAR = uiAddress; //地址EEDR = ucData; //数据EECR |=(1<<EEMWE); //置位EEMWE,主机写使能EECR |=(1<<EEWE); //置位EEWE,写使能,启动写操作}/*从EEPROM指定的地址里面读出相应的数据*/unsigned char EEPROM_read(unsigned int uiAddress){while(EECR&(1<<EEWE)); //等待上一次写操作结束EEAR = uiAddress; //设置地址寄存器EECR |=(1<<EERE); //读使能return EEDR; //返回读入EEDR里面的数据}void main(void){unsigned char temp=123;unsigned char data;HC_595_init();EEPROM_write(0x01,temp);data=EEPROM_read(0x01);while(1){Seg7_Led_display(data); //调用显示函数将写入的数据又读出来 }}文件:eeprom12.rar大小:40KB下载:下载4、定时器0(轮循方式)/*定时器0和2(均为八位的定时计数器)有四种工作模式,此例是工作在普通模式。
基于MEGA128单片机的低能离子注入的无线智能控制系统的设计与实现
基于MEGA128单片机的低能离子注入的无线智能控制系统的设计与实现刘南君;毛培宏【期刊名称】《新疆大学学报(自然科学版)》【年(卷),期】2013(000)001【摘要】Low energy ion implantation, as a new gene mutation method are widely used in biological breeding field. Aim at the problem in the electrical control mechanism of LZD1000 low energy ion implan-tation machine, a set of wireless intelligent control system was designed basedon AVRmega128 single chip microcomputer, and the system’s hardware and software debugging were completed. The results showed that the design and production of the master control board and LZD1000 low energy ion implantation machine system realized the good compatibility, and achieved the desired purpose.%低能离子注入作为一种新型基因诱变手段广泛应用于生物育种。
针对LZD1000型低能离子注入机在操作控制中存在的问题,本文设计了一套基于AVRmega128单片机的无线智能控制系统,完成了系统的硬件和软件的调试。
本设计制作的主控板与LZD1000型低能离子注入机系统实现了完好的兼容,达到了预期的目的。
tm1627测试程序(mega128)
TM1627_CN:/view/b3a01509763231126edb116a.html注:1、上述说明文档中图18的上拉电阻和电容是成对的接在STB、CLK、DIO上的。
2、我在测试电路中仅在DIO上使用了2kΩ的上拉电阻,没有使用电容。
且在使用10kΩ上拉电阻时没有读到正确的值,原因未知。
3、我使用的主控芯片为mega128(16MHz),使用引脚见程序。
4、说明文档中提到读取数据时需要在CLK上升沿读取DIO电平,但是我在使用中遇到CLK上升沿读取DIO电平不准确的情况,最后改为在CLK下降沿读取DIO电平,数据准确。
5、在下属程序使用前PA口的0、1、2位已初始化为输出状态。
6、对IO口初始化后调用disp()即可显示数字,调用key_get()可得到处理后的键值(处理方法因键盘设计而异)等待按键按下、松开与两个按键同时按下检测的程序段为:/*************************************************************************/unsigned char temp_kv=0,kv=0;/*************************************************************************/temp_kv = key_get();//将键值赋给temp_kvwhile((temp_kv==13)||(inover==1)) //等待按键按下temp_kv = key_get();kv = temp_kv; //获得键值while((temp_kv!=13)||(inover==1)) //等待按键松开或输入完成{temp_kv=key_get();if(temp_kv==12) //若两个功能键都被按下,kv=12;}/**************************************************************************///头文件tm1627.h#define TM1627_H//#include <avr/io.h>#define CLR_0_STB PORTA&=0xFE //STB:PA0#define SET_1_STB PORTA|=0x01#define CLR_0_CLK PORTA&=0xFD //CLK:PA1#define SET_1_CLK PORTA|=0x02#define CLR_0_DIO PORTA&=0xFB //DIO:PA2#define SET_1_DIO PORTA|=0x04#define DIO_READ DDRA&=0xFB /*DIO设为输入电平读取*/#define DIO_SEND DDRA|=0x04 /*DIO设为输出*///unsigned char table[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};extern unsigned char liangdu;extern unsigned char key_val;void delay_ms(unsigned char cn);void TM1627_write(unsigned char dat);unsigned char TM1627_read(void);void disp(unsigned int dat,unsigned char led);//显示函数显示一个unsigned int型数据并控制三个LED的亮暗unsigned char key_get(void);//返回已转换过的键值(0-12),其中键值12为S4和S12同时按下的键值//tm1627.c#include <avr/io.h>#include "tm1627.h"/*#define CLR_0_STB PORTA&=0xFE //STB:PA0#define SET_1_STB PORTA|=0x01#define CLR_0_CLK PORTA&=0xFD //CLK:PA1#define SET_1_CLK PORTA|=0x02#define CLR_0_DIO PORTA&=0xFB //DIO:PA2#define SET_1_DIO PORTA|=0x04*/unsigned char table[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};//数码管码表unsigned char key[5];//unsigned char last_kv=12;void del(unsigned char cn){for(;cn>0;cn--);}unsigned char key_get(void){unsigned char i,j;unsigned char key_val;CLR_0_STB;TM1627_write(0x42);//读数据DIO_READ;// DDRA&=0xFB;//DIO设为输入// PORTA|=0x04;//使能上拉电阻TM1627j = PINA;for(i=0;i<5;i++){key[i]=TM1627_read();del(40);}SET_1_STB;DIO_SEND;// DDRA|=0x04;//DIO设为输出if(key[0]==0x01)key_val=1;else if(key[0]==0x08)key_val=2;else if(key[1]==0x18)key_val=12;else if(key[1]==0x01)key_val=3;else if(key[1]==0x08)key_val=10;else if(key[2]==0x01)key_val=4;else if(key[2]==0x08)key_val=5;else if(key[3]==0x01)key_val=6;else if(key[3]==0x08)key_val=0;else if(key[0]==0x02)key_val=7;else if(key[0]==0x10)key_val=8;else if(key[1]==0x02)key_val=9;else if(key[1]==0x10)key_val=11;elsekey_val=13;return key_val;}unsigned char TM1627_read(void) {unsigned char i;unsigned char temp=0;unsigned char bit;// SET_1_CLK;bit = PINA&0x04;for(i=0;i<8;i++){// temp>>=1;CLR_0_CLK;// for(j=0;j<20;j++);bit = PINA&0x04;if(bit == 0x04)temp|=0x80;//最高位置1SET_1_CLK;temp>>=1;// for(j=0;j<20;j++);}return temp;// SET_1_CLK;}void disp(unsigned int dat,unsigned char led) {// unsigned char ge,shi,bai,qian;unsigned char wei[4]={0,0,0,0};unsigned char i;wei[3]=dat%10;wei[2]=dat/10%10;wei[1]=dat/100%10;wei[0]=dat/1000;DDRA|=0x04;//DIO设为输出CLR_0_STB;TM1627_write(0x03);//7位10段SET_1_STB;delay_ms(5);CLR_0_STB;TM1627_write(0x40);//地址自动加一SET_1_STB;delay_ms(5);CLR_0_STB;TM1627_write(0xC0);//以下是14字节数据 for(i=0;i<4;i++){TM1627_write(table[wei[i]]);TM1627_write(0x00);}TM1627_write(led);TM1627_write(0x00);SET_1_STB;// delay_ms(5);CLR_0_STB;TM1627_write(liangdu);//脉冲宽度// TM1627_write(0x8F);//脉冲宽度SET_1_STB;}void TM1627_write(unsigned char dat){unsigned char i;// DIO_OUT(); //将DIO设置为推挽输出for(i=0;i<8;i++){CLR_0_CLK; //先将CLK置低if((dat&0x01)==0x01)SET_1_DIO; //将数据发至DAT线上elseCLR_0_DIO;dat >>= 1; //数据移位准备下一次的发送// delay_ms(3); //延时以等待TM1627接收SET_1_CLK; //将CLK置高del(10);}// SET_1_CLK;}void delay_ms(unsigned char cn)//不准确的延时{unsigned char i,j;for(;cn>0;cn--){for(i=0;i<100;i++)for(j=0;j<255;j++);}}电路原理图:。
AVR单片机Mega128 485通信程序
AVR单片机Mega128 485通信程序一、实物测试二、程序//#include <io.h> //用这个头文件也可以#include <mega128.h>#include <string.h>#include <stdio.h>#define F_CPU 16000000 // 单片机主频为16MHz,用于延时子程序,熔丝位必须设置到外部高频晶振才行#include "Config.h" //配置头文件,与硬件相关的配置在这里更改#define LED0 PORTE.0#define LED1 PORTE.1#define LED2 PORTE.2#define LED3 PORTE.3#define LED4 PORTE.4#define LED5 PORTE.5#define LED6 PORTE.6#define LED7 PORTE.7#define PD4 PORTD.4unsigned char str[50]={0};unsigned char in=0,a=0,lage=0;//uchar usart_rx_data;void delay_ms(int ms){for(;ms>0;ms--);}//************************************************ ***********************// MSP430IO口初始化//************************************************ ***********************void Port_Init(){LEDDDR = 0xFF; //设置IO口方向为输出LED = 0xFF; //PE口初始设置为FFDDRD = 0x18; //设置为输入,并且要打开上拉电阻//DDRD = 0x00 | (1<<RS485_CTR_RDE)| (1<<PD3);//PORTD |= ((1 << PD1) |(1 << PD5)|(1 << PD6)|(1 << PD7)); //四位独立按键连接在PD1/PD5/PD6/PD7上}//************************************************ *************************// MSP430串口1初始化//************************************************ *************************void UART1_Init(){UCSR1A=0x00; //单倍速模式UCSR1B=0x98; //接收中断允许,发送结束和寄存器空中断关闭,采用查询发送模式//UCSR1B=0x08;//UCSR1C=(1<<UCSZ11)|(1<<UCSZ10); //写UCSRC寄存器,异步通信无校验,8位数据1位停止位UCSR1C=0x86;UBRR1H=0; //写波特率的值UBRR1L=103;}//************************************************ *************************// 串口1发送数据函数//************************************************ *************************void Send_Byte(uchar data){while(!(UCSR1A&(1<<UDRE1))); //等待发送寄存器空UDR1= str[data]; //写入发送数据while(!(UCSR1A&(1<<TXC1))); //等待发送完毕UCSR1A|=(1<<TXC1);delay_ms(5); //切换之前先有个小延时}//************************************************ *************************// 处理来自串口1的接收中断//************************************************ *************************//数据接收结束中断向量interrupt[USART1_RXC]void usart_rx_isr(void)//中断服务程序{str[in]=UDR1;LED0=0;if(str[in]!=0x0A) //$为停止标志{in++;}else{LED3=0;in=0;lage=1;}}//************************************************ *************************// 主函数//************************************************ *************************void main(void){DDRE=0xFF;PORTE=0XFF;Port_Init(); //端口初始化UART1_Init(); //串口设置初始化PD4=0; //切换到接收状态delay_ms(2);SREG|=0x80; //开启全局中断while(1) //无限循环{if(lage==1){PD4=1; //开启发送for(a=0;;a++){Send_Byte(a);if(str[a]==0x0A){//lage=0; //放在这个位置也可以//PD4=0; //放在这个位置也可以break; //跳出循环}}a=0;lage=0;LED5=0;PD4=0;}}三、仿真原理图。
AVR单片机Atmega128在FPGA配置中的运用
编程型价格昂贵 ,且容量有限 ,对容量较大的可编程 逻辑器件 ,需要多片配置芯片组成菊花链形进行配 置 ,增加系统设计的难度 。为此,利用MCU 对 FPGA 进行配置具有非常实用的价值 ,特别是 AVR单片机 ATmega128,由于它具有 128K的 Flash存储器 ,在无 须外部存储器扩展的情况下 ,也能实现对 FPGA 的 配置 。下面将以 ATmega128对 EPF10K10的被动串 行配置为例 ,介绍其配置的软硬件设计原理 。
中除 EPF10K70 外的各种器件实现配置 。在系统
中 ,配置程序 、系统的用户应用程序以及配置文件在
内的. rbf文件 ,经过组合后 ,形成一个新的. hex文
件 ,它通过 SP I接口下载到 ATmega128 的 Flash 程
序存储器中 。系统上电后 ,在配置程序的控制下 ,包
括配置文件在内的. rbf文件中的数据通过串行口对
109
图 1 被动配置时序图
MAX + PLUS II开发工具可以生成多种配置或 编译文件 ,用于不同配置方法的配置系统 ,而对于不 同系列的目标器件配置数据的大小也不同 ,如表 2 所示 。配置文件的大小一般由. rbf文件决定 。. rbf 文件即二进制文件 ,该文件包括所有的配置数据 ,一 个字节的. rbf文件有 8 位配置数据 ,每一字节在配 置时最低位最先被装载 。单片机 ATmega128 可以 读取这个二进制文件 ,并把它装载到目标器件中 。 A ltera提供的软件工具不自动生成. rbf文件 ,须按照 下面的步骤生成 : ①在 MAX + PLUS II编译状态 ,选 择文件菜单的变换 SRAM 目标文件命令 ; ②在变换 SRAM 目标文件对话框 ,指定要转换的文件并且选 择输出文件格式为. rbf,然后确定 。
mega128技术文档
雪松电子开发:/AVR mega128 技术文档1、电路分析图(1)mega128 核心板原理图 一,硬件电路说明 1,电源:1)通过 ISP 连接 USB 进行供电。
2)通过 JTAG 连接 USB 供电。
3)通过 P5 外接 5V 电源供电。
2,外围接口:P1,P2,P3,P4 共 64 位将 mega128 所有的接口全部引出,方便工程设 计和外围扩展。
3,发光二极管 D0 的作用是指示电源是否连接成功,如果外部电源成功的连接上,则发 光二极管发光指示电源连接成功;电阻 R0 的作用是对发光二极管进行限流,一般发光二极 管只能通过 5mA—15mA 左右的电流,且发光二极管上面的压降只需要 1.5V 左右,加到发 光二极管上面的电流如果超出额定值,则会烧毁。
而系统工作的电压是 5V,如果全部加在 发光二极管上, 则发光二极管很容易就会被烧毁。
所以要在电源和发光二极管之间串接一个 限流电阻。
该限流电阻阻值的计算: (VCC-发光二极管上的电压)/流过发光二极管的电流。
一般发光二极管的压降是 1.5V 左右,电流为 10mA 左右,为降低功耗我们在此取 680R 发光二极管 D1 和 R1 的作用是作为程序运行指示,在程序运行的过程中通过跳冒 P0 选 通 4,复位电路:单片机的第 20 脚(RESET,复位管脚)经过按钮 S0 连接到地。
分析:a)AVR 单片机是低电平复位(51 单片机是高电平复位,刚好相反) 。
需要 单片机复位时,最少要在复位管脚加上 1.5 微秒的低电平,才能确保单片机正确复位。
b)按下按钮 S0,复位管脚被直接拉到电源地,这样复位管脚的电平就被 拉低,从而使单片机复位;一般情况下按钮按下的时间超过毫秒级别,这样就能确保单片机“雪松电子开发”你身边的嵌入式开发专家雪松电子开发:/正确复位。
5, ISP 电路(程序下载电路) :ISP 下载接口不需要任何的外围零件。
基于MEGA128的运动器设计与实现
(上接第 447 页)
3 评分问题
在比赛中,为选手打分、评分是经常要遇到的事情,下例就是 使用 Excel 的函数实现对评委的打分在去掉最高、 最低分之后求 其平均分的例子。 在 I2 中输入以下公式:
=(SUM(B2:H2)-MAX(B2:H2)-MIN(B2:H2))/(COUNT(B2:H2)-2), 将公式复制到 I3~I7,得到如图 3 所示效果。
……
case 0x64:dir_port=1;break;
// 选 择 正 转
……
} //switch 结束
} //while 结束
} //main 结束
4 结语
经过硬件调试及软件测试,本装置工作正常,整体可靠性比较高,缺点在于功能不够丰富,比如可以增加网络监测及控制功能, 提供基于 TCP/IP 的远程运动控制功能,可以增加视频监测网络化功能等等,可以在下步工作中进一步改进。
ISSN 1009-3044
CCoommppuutteerr KKnnoowwlleeddggee Aanndd TTeecchhnnoollooggyy 电电脑脑知知识识与与技技术术 Vol.5,No.2,January 2009, pp.458-459
E-mail: kfyj@ 第 5 卷第 2 h期ttp:/(/2w0w0w9.d年nzs1.n月et.)cn
图 3 评分应用示例
4 结束语
通过教学实践,不难体会到范例教学法在 Excel 教学中的优势。 对于以上范例,如果在教学过程中能将其融入一个综合应用情 境时,可产生更好的效果。
参考文献:
[1] 李艺,李冬梅.信息技术教学方法:继承与创新[M].北京:高等教育出版社,2003:252-277. [2] 王业根.Excel 中公民身份号码的验证[J].科技资讯,2008:148-.单片机应用系统开发实例详解[M].北京:机械工业出版社,2007. [2] 靳达.单片机应用系统开发实例导航[M].北京:人民邮电出版社,2004. [3] 高守传,聂云铭,郑静.Visual C++开发指南[M].北京:人民邮电出版社,2007. [4] 胡志坤.Visual C++通信编程工程实例精解[M].北京:机械工业出版社,2007. [5] 龚建伟,熊光明.Visual C++/Turbo C 串口通信编程实践[M].2 版.北京:电子工业出版社,2007.
- 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;}}}/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 可靠地判断帧结束,防止通信停滞/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 利用单独的软件定时器,来判断一帧接收报文结束,可以防止若报文接收不完整,该帧通信任务无法结束而影响下一帧的接收。