当前位置:首页 > proteus仿真
  • 关于proteus仿真的串口问题

    以下四幅图都是关于串口中断的问题,串口中断需要一个接收或者发送数据的触发。 图一:因为由串口小助手发送的数据达到了单片机串口,所以引起了串口的中断。   图二:图一的大图。   图三:因为由串口小助手发送的数据达到了virtual terminal,没有到达串口,所以没有引起串口的中断。   图四:图一和图三的综合,也不行   main.c #include "os_cfg.h" #include "task0.h" #include "task1.h" #include "task2.h" #include "task3.h" void (* code task[])() = {task0,task1,task2,task3}; void main(void) { uchar i; os_timer0_init(); os_timer1_init(); EA = 1; //开总中断 while(1) { for(i=0;iif (task_delay[i]==0) {run(task[i]); break;} //任务优先级调度 } } os_cfg.h #include "reg52.h" #include "macroandconst.h" #define TIME_PER_SEC 200 //定义任务时钟频率,200Hz #define CLOCK 22118400 //定义时钟晶振,单位Hz #define MAX_TASK 4 //定义任务数量 extern unsigned char task_delay[MAX_TASK]; extern void run(void (*ptask)()); extern void os_timer0_init(void); extern void os_timer1_init(void); macroandconst.h #ifndef _MACRO_AND_CONST_H_ #define _MACRO_AND_CONST_H_ typedef unsigned int uint16; typedef unsigned int UINT; typedef unsigned int uint; typedef unsigned int UINT16; typedef unsigned int WORD; typedef unsigned int word; typedef int int16; typedef int INT16; typedef unsigned long uint32; typedef unsigned long UINT32; typedef unsigned long DWORD; typedef unsigned long dword; typedef long int32; typedef long INT32; typedef signed char int8; typedef signed char INT8; typedef unsigned char byte; typedef unsigned char BYTE; typedef unsigned char uchar; typedef unsigned char UINT8; typedef unsigned char uint8; typedef unsigned char BOOL; #endif task0.h #ifndef _TASK0_H_ #define _TASK0_H_ extern void task0(unsigned int db); #endif task1.h #ifndef _TASK1_H_ #define _TASK1_H_ #define ADC0804_DB P1 extern void task1(void); #endif task2.h #ifndef _TASK2_H_ #define _TASK2_H_ extern void task2(void); #endif task3.h #ifndef _TASK3_H_ #define _TASK3_H_ extern void task3(void); #endif os_c.c #include "os_cfg.h" #include "task1.h" uchar task_delay[MAX_TASK]; uchar data_buffer; //定时器0初始化 void os_timer0_init(void) { uchar i; for(i=0;iTMOD = (TMOD & 0XF0) | 0X01; //定时器0工作在模式1,16Bit定时器模式 TH0 = (65536-CLOCK/TIME_PER_SEC/12) / 256; //CRY_OSC,TIME_PER_SEC在easycfg.h中配置 TL0 = (65536-CLOCK/TIME_PER_SEC/12) % 256; TR0 =1; ET0 =1; //开启定时器和中断 } //定时器1初始化 void os_timer1_init(void) { SCON = 0x50;//串行口工作方式1,REN=1允许接受串行数据 PCON = 0; //电源控制寄存器 SMOD=0,波特率保持不变 TMOD = 0x20; //定时器T1初始化,工作方式2 TH1 = 0xFD; //产生波特率为9600bit/s的计数初值 TL1 = 0xFD; TR1 = 1; ES = 1; //允许串口中断 } // 系统OS定时中断服务 void os_timer0(void) interrupt 1 { uchar i; TH0 = (65536-CLOCK/TIME_PER_SEC/12) / 256; //CRY_OSC,TIME_PER_SEC在easycfg.h中配置 TL0 = (65536-CLOCK/TIME_PER_SEC/12) % 256; for(i=0;i} void os_timer1(void) interrupt 4 { SBUF = ADC0804_DB; while(!TI); //等待发送完成 TI = 0; //清零发送标志位 if(RI) //RI接收中断标志位 { RI=0; SBUF = data_buffer;//发送数据 data_buffer = SBUF;//读取数据 } // if(TI) //TI发送中断标志位 // { // TI=0; // } } void run(void (*ptask)()) { (*ptask)(); } task0.c #include "os_cfg.h" #include "delay.h" #define TASK_DELAY0 TIME_PER_SEC/40 //数码管频度为40Hz /*---------共阴极0~f数码管编码 ----------*/ uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66, 0x6d,0x7d,0x07,0x7f,0x6f}; void task0(uint db) { /*为什么位选放在段选前面就不行了呢?*/ uchar bw,sw,gw; //bw,sw,gw分别等于db百位,十位,个位上的数 db=db*100/50; bw=db/100; sw=db%100/10; gw=db%10; P2=0xfe; //点亮第一只数码管 P0=table[bw]|0x80; //最高位置0,点亮第一只数码管的小数点, delay(1); P2=0xfd; //点亮第二只数码管 P0=table[sw]; delay(1); P2=0xfb; //点亮第三只数码管 P0=table[gw]; delay(1); P2=0xf7; //点亮第四只数码管 P0=table[0]; //第四只数码管一直显示0 delay(1); task_delay[0] = TASK_DELAY0; } task1.c #include "os_cfg.h" #include "delay.h" #include "intrins.h" #include "task0.h" #include "task1.h" //static uchar i; sbit wr=P3^6; sbit rd=P3^7; #define TASK_DELAY1 TIME_PER_SEC/41 //任务执行频度为60Hz void task1(void) { wr=0; //在片选信号CS为低电平情况下(由于CS接地,所以始终为低电平), _nop_(); //WR由低电平到高电平时,即上升沿时,AD开始采样转换 wr=1; delay(1); //延时1ms,等待采样转换结束,延时函数 delay(1)延时0.992ms,大约为1ms //P1=0xff; //这条语句不能少,我也还不知道为什么 rd=0; //将RD脚置低电平后,再延时大于135ns左右(这里延时1us), _nop_(); //即可从DB脚读出有效的采样结果,传送到P1口 //for(i=0;i<10;i++) //刷新显示一段时间 task0(ADC0804_DB); //显示从ADC0804的DB得到的数字量 task_delay[1] = TASK_DELAY1; } task2.c #include "os_cfg.h" #define TASK_DELAY2 TIME_PER_SEC/10 //任务执行频度为10Hz void task2(void) { // SBUF = dat; //待发送的数据写入缓冲区 // while(!TI); //等待发送完成 // TI = 0; //清零发送标志位 task_delay[2] = TASK_DELAY2; } task3.c #include "os_cfg.h" #define TASK_DELAY3 TIME_PER_SEC/20 //任务执行频度为20Hz void task3(void) { task_delay[3] = TASK_DELAY3; } delay.h #ifndef _DELAY_H_ #define _DELAY_H_ extern void delay(unsigned int x); #endif delay.c #include #include "macroandconst.h" static uchar i; void delay(uint x) //延时函数 delay(1)延时0.992ms,大约为1ms { while(x--) for(i=0;i<120;i++); } 程序的目的是:通过ADC0804采集数据,通过数码管显示,并上传到上位机,这是程序的初稿,有待完善,欢迎提意见。 附上仿真图:  

    时间:2019-07-06 关键词: proteus仿真 串口问题

  • Proteus仿真与实际的差别

    弄了几天的Proteus仿真,终于觉得自己想做的东西,已经全部用Proteus仿真过了,应该可以动手做了。于是先用Proteus画好原理图,再用ARES画好PCB板图——虽然我只是用洞洞板焊接,但是有个PCB板图做参照,连线会容易很多。花了两个小时,去中关村买了必要的原件,开始动手。 单片机用的是STC89C552RC,原因除了价廉物美之外,最大的原因是,STC的单片机可以直接使用串口往里面下程序,这样我可以直接焊接好板子,然后连接好串口,一边写一边调试,不用把单片机拿来拿去了。为了焊的好看些,把线基本都布在了反面,前前后后,修修改改,共焊了3天才弄好,搞得眼睛一闭上都是洞洞板的圈圈。 不过通过这次的实际制作,还真发现了不少Proteus仿真中不会想到的问题,现记录如下,希望以后再碰到时,可以作为参考。 碰到的第一个问题,就是程序怎么也下载不到单片机中去。在Proteus仿真的时候,并不需要往单片机中写程序,编译好后,程序就已经在单片机中了,但是实际制作时,就得编译一次程序,下载一次。结果我在下载时,发现提示“不能连接到串口”,让我实在是头疼不已。试着用“串口助手”往单片机发数据时,发现数据指示类会闪烁,说明线路是通了。百思不得其解之下,同事提醒我说,是不是你这两个数据传送指示灯有问题?虽然我觉得成分的不可能,可是试着把两个LED灯去掉之后,还真可以了…… 这是先前的电路图(省略MAX232芯片)   结果串口在给单片机发数据的时候,灯是会闪烁的,让我坚定的以为,串口的通路是没问题的。后来把电路改成这样,串口不能通信,不能下载程序的问题就好了   终于把串口弄好了,程序下载到了单片机上,结果效果和proteus上模拟的完全不一样。Proteus上的话,1602显示器直接就显示数据了,结果到了现实,什么都没有……死命的调节对比度电阻,也还是什么都没有,真的感觉无从下手了。后来去群里问,群里的老大给了一个示例程序,用上去也还是不行,这让我真的是感觉要崩溃了。不过想想焊了这么多天,放弃实在是不甘心,于是把所有和液晶显示不相关的代码全注释掉了,突然发现莫名其妙的,液晶出现了色块——当时感觉是太开心了,一天了,终于液晶上有显示了!不过此时仍然不能设置显示字符,不过相比没有任何显示已经好太多了。 同样的代码,为什么这次可以了呢?仔细的分析了代码,发现这次的代码,唯一的不同,就是我为了少写几个字,延时函数用的是群里老大给的。这是唯一的不同之处。比对一下两个延时1毫秒的函数。 我自己的: ? 1 2 3 4 5 6void delay(unsigned char ms) { unsigned char i,j; for(i=0; i for(j=0; j<120; j++); } 群里老大给的: ? 1 2 3 4 5 6void delay(int ms) { int i,j; for(i=0; i for(j=0; j<120; j++); } 没错,两个函数唯一的区别,就是变量的类型,我写的时候,看变量都不会超过255,为了省点空间,定义的都是unsigned char,而一般的延时函数,用的是int类型,就是这两个变量类型的不同,导致了延时的不同,同样是想延时1毫秒,我的函数实际上只能延时0.4到0.5毫秒左右,就是这个的区别,让我在操作液晶时,各个时序的延时不够,给液晶的命令不能到达。后来修改后,再修改了一下程序其他地方,终于让液晶正确的显示了。 再说一个比较郁闷的事情,在Proteus里面,1602是这样显示的     买来实物后,我也理所当然的认为,有焊点的是下方(事实上我确实认为这样比较符合心理,哈哈)。结果程序写后好,一显示出来,全倒过来了………… 不管怎么说,今天总算让板子上的元件都工作正常了。明天开始改程序,实现具体功能。

    时间:2019-06-26 关键词: proteus仿真

  • Proteus仿真与实际的差别

    弄了几天的Proteus仿真,终于觉得自己想做的东西,已经全部用Proteus仿真过了,应该可以动手做了。于是先用Proteus画好原理图,再用ARES画好PCB板图——虽然我只是用洞洞板焊接,但是有个PCB板图做参照,连线会容易很多。花了两个小时,去中关村买了必要的原件,开始动手。单片机用的是STC89C552RC,原因除了价廉物美之外,最大的原因是,STC的单片机可以直接使用串口往里面下程序,这样我可以直接焊接好板子,然后连接好串口,一边写一边调试,不用把单片机拿来拿去了。为了焊的好看些,把线基本都布在了反面,前前后后,修修改改,共焊了3天才弄好,搞得眼睛一闭上都是洞洞板的圈圈。不过通过这次的实际制作,还真发现了不少Proteus仿真中不会想到的问题,现记录如下,希望以后再碰到时,可以作为参考。碰到的第一个问题,就是程序怎么也下载不到单片机中去。在Proteus仿真的时候,并不需要往单片机中写程序,编译好后,程序就已经在单片机中了,但是实际制作时,就得编译一次程序,下载一次。结果我在下载时,发现提示“不能连接到串口”,让我实在是头疼不已。试着用“串口助手”往单片机发数据时,发现数据指示类会闪烁,说明线路是通了。百思不得其解之下,同事提醒我说,是不是你这两个数据传送指示灯有问题?虽然我觉得成分的不可能,可是试着把两个LED灯去掉之后,还真可以了……这是先前的电路图(省略MAX232芯片)结果串口在给单片机发数据的时候,灯是会闪烁的,让我坚定的以为,串口的通路是没问题的。后来把电路改成这样,串口不能通信,不能下载程序的问题就好了终于把串口弄好了,程序下载到了单片机上,结果效果和proteus上模拟的完全不一样。Proteus上的话,1602显示器直接就显示数据了,结果到了现实,什么都没有……死命的调节对比度电阻,也还是什么都没有,真的感觉无从下手了。后来去群里问,群里的老大给了一个示例程序,用上去也还是不行,这让我真的是感觉要崩溃了。不过想想焊了这么多天,放弃实在是不甘心,于是把所有和液晶显示不相关的代码全注释掉了,突然发现莫名其妙的,液晶出现了色块——当时感觉是太开心了,一天了,终于液晶上有显示了!不过此时仍然不能设置显示字符,不过相比没有任何显示已经好太多了。同样的代码,为什么这次可以了呢?仔细的分析了代码,发现这次的代码,唯一的不同,就是我为了少写几个字,延时函数用的是群里老大给的。这是唯一的不同之处。比对一下两个延时1毫秒的函数。我自己的:?123456voiddelay(unsignedcharms){unsignedchari,j;for(i=0; i

    时间:2018-12-20 关键词: 实际 proteus仿真

  • proteus仿真之DS1302+8位数码管显示试验

    proteus仿真之DS1302+8位数码管显示试验。仿真效果如下图:源程序如下:/*51单片机:DS1302+数码管 Proteus 仿真程序。功能:数码管时钟显示。仿真结果:(1)8位数码管显示设定的时间与日期。(2)通过按键切换时间与日期的显示。*/#include sbit LE_DUAN = P2^0; //定义573锁存使能端口 数码管段锁存sbit LE_WEI = P2^1; //定义573锁存使能端口 数码管位锁存#define SEGPORT P0 //定义数码管连接端口sbit SCK = P3^6;// DS1302时钟线sbit SDA = P3^4;// DS1302数据线sbit RST = P3^5; // DS1302复位线//DS1302 复位重定义#define RST_CLRRST=0//电平置低#define RST_SETRST=1//电平置高//DS1302 数据#define SDA_CLRSDA=0//电平置低#define SDA_SETSDA=1//电平置高#define SDA_RDSDA //电平读取//DS1302 时钟#define SCK_CLRSCK=0//时钟信号#define SCK_SETSCK=1//电平置高#define DS1302_SEC0x80//秒数据地址#define DS1302_MIN0x82//分数据地址#define DS1302_HOUR0x84//时数据地址#define DS1302_DATE0x86//日数据地址#define DS1302_MON0x88//月数据地址#define DS1302_DAY0x8a//星期数据地址#define DS1302_YEAR0x8c//年数据地址#define DS1302_CTRL0x8e//控制数据地址#define DS1302_CHARGE0x90 //涓流充电bit ReadRTC_Flag; //读DS1302标志。1为读 0为不读。unsigned char TimeMode; //日期与时间切换标志。unsigned char time_buf1[8] = {40,14,2,14,10,59,50,7};// -年月日时分秒周2014-02-14 10:59:50 7周unsigned char time_buf[8] ; // -年月日时分秒周unsigned char TempData[8] ;unsigned char code Seg_Wei[]= {0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; //数码管的位码,低电平有效。unsigned char code Seg_Duan[]= {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40}; //共阳数码管显示段码值 0~9,-void DS1302_Init(void);void DS1302_Write_Byte(unsigned char addr, unsigned char d);unsigned char DS1302_Read_Byte(unsigned char addr) ;void DS1302_Read_Time(void);void DS1302_Write_Time(void);void Seg_Disp(unsigned char FirstBit,unsigned char Num);void InitTIMER0(void);//inital timer0void Delay_1ms(unsigned int i);unsigned char GetKey(void);void main(void){unsigned char Key; InitTIMER0();DS1302_Init();DS1302_Write_Time();P2=0xff; //51默认为输入while(1){Key = GetKey();if(Key&0x01){TimeMode = ~TimeMode; //有按键后,模式取反,改变当前显示模式}if(ReadRTC_Flag==1){ReadRTC_Flag=0;DS1302_Read_Time();if(TimeMode){TempData[0]=Seg_Duan[time_buf1[1]/10];//年 数据的转换,TempData[1]=Seg_Duan[time_buf1[1]%10];//因我们采用数码管0~9的显示,将数据分开TempData[2]=0x40; //加入"-"TempData[3]=Seg_Duan[time_buf1[2]/10];//月TempData[4]=Seg_Duan[time_buf1[2]%10];TempData[5]=0x40;TempData[6]=Seg_Duan[time_buf1[3]/10];//日TempData[7]=Seg_Duan[time_buf1[3]%10];}else{TempData[0]=Seg_Duan[time_buf1[4]/10];//时 数据的转换,TempData[1]=Seg_Duan[time_buf1[4]%10];//因我们采用数码管0~9的显示,将数据分开TempData[2]=0x40; //加入"-"TempData[3]=Seg_Duan[time_buf1[5]/10];//分TempData[4]=Seg_Duan[time_buf1[5]%10];TempData[5]=0x40;TempData[6]=Seg_Duan[time_buf1[6]/10];//秒TempData[7]=Seg_Duan[time_buf1[6]%10];}}}}/*------------------------------------------------ DS1302初始化------------------------------------------------*/void DS1302_Init(void){RST_CLR;//RST脚置低SCK_CLR;//SCK脚置低DS1302_Write_Byte(DS1302_SEC,0x00);}/*------------------------------------------------ 向DS1302写入一字节数据------------------------------------------------*/void DS1302_Write_Byte(unsigned char addr, unsigned char dat){unsigned char i;RST_SET;addr = addr & 0xFE; //写地址 最低位为W写,低电平for (i = 0; i < 8; i++){if (addr & 0x01){SDA_SET;}else{SDA_CLR;}SCK_SET;SCK_CLR;addr = addr >> 1;}//写入数据:datfor (i = 0; i < 8; i ++) {if (dat & 0x01) {SDA_SET;}else {SDA_CLR;}SCK_SET;SCK_CLR;dat = dat >> 1;}RST_CLR;//停止DS1302总线}/*------------------------------------------------ 从DS1302读出一字节数据------------------------------------------------*/unsigned char DS1302_Read_Byte(unsigned char addr){unsigned char i;unsigned char temp;RST_SET;addr = addr " 0x01;//最低RD,有效为高电平for (i = 0; i < 8; i ++){if (addr & 0x01){SDA_SET;}else{SDA_CLR;}SCK_SET;SCK_CLR;addr = addr >> 1;}//输出数据:tempfor (i = 0; i < 8; i ++){temp = temp >> 1;if (SDA_RD){temp |= 0x80;}else{temp &= 0x7F;}SCK_SET;SCK_CLR;}RST_CLR;//停止DS1302总线return temp;}/*------------------------------------------------ 从DS1302读出时钟数据------------------------------------------------*/void DS1302_Read_Time(void){ unsigned char i,tmp;time_buf[1]=DS1302_Read_Byte(DS1302_YEAR);//年time_buf[2]=DS1302_Read_Byte(DS1302_MON);//月time_buf[3]=DS1302_Read_Byte(DS1302_DATE);//日time_buf[4]=DS1302_Read_Byte(DS1302_HOUR);//时time_buf[5]=DS1302_Read_Byte(DS1302_MIN);//分time_buf[6]=(DS1302_Read_Byte(DS1302_SEC))&0x7F;//秒time_buf[7]=DS1302_Read_Byte(DS1302_DAY);//周for(i=0;i

    时间:2018-12-03 关键词: ds1302 数码管显示 proteus仿真

  • avr单片机proteus仿真第四课:控制继电器

    继电器(Relay),作用是用弱电控制强电。比如,我们用avr单片控制一个220V电压的灯泡,这就必须用到继电器。本课用avr单片机来控制继电器的吸合与断开。Proteus仿真实验器件:1 atmega128一块2 button,按键一个3 relay,通用继电器一个,并把继电器的Component Value设置为5V4 pnp三极管一个5 LAMP,灯泡一个改为220V6 resistor 1k7 DIODE 二极管一个这个程序实际上很简单,主要要学习继电器的用法,注意的是,继电器必须接一个二极管。仿真程序如下:#include#include#define int8u unsigned char#define int16u unsigned int#define k1_down() (PINB & _BV(PB7))#define relay_switch() PORTD^=_BV(PD4)int main(){DDRD=0xff;PORTD=0xff;DDRB=0x00;PORTB=0xff;while(1){ if(k1_down() ){ while(k1_down() ); relay_switch( ); _delay_ms(20);}}}

    时间:2018-11-23 关键词: avr单片机 控制继电器 proteus仿真

  • 单片机按键与数码管试验程序 Proteus仿真

    最近温习一下单片机,通过proteus 7.8仿真了一下,感觉效果不错。单片机程序如下:/*51单片机 按键与数码管实验,用proteus 7.8仿真通过。通过点按键,K1:数码管数字加一,0~F,加上F后再从0开始。K2:数码管数字减一,F~0,减到0后再从F开始减K3:复位这零.*/#include //#include unsigned char RunMode;unsigned char code SegCode[] = { 0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,//共阳 0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E,0xFF};//0~F#define SegDataPort P3/********************************/void delay_1ms(unsigned int i) //最小延时1ms{unsigned char j;while(i--)for(j=0;j

    时间:2018-11-09 关键词: 按键 单片机 数码管 proteus仿真

  • avr单片机proteus仿真第三课:单只数码管

    数码管选7SEG-MPX1-CC,共阴极数码管。也就是低电平选通(最右脚),数码管左边8只管脚,从左到右,由低到高,分别接PC0---PC7。c程序如下:#include#include#define int8u unsigned char#define int16u unsigned intconst int8u seg_code[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};int main(){int8u i=0;DDRC=0xff;while(1){PORTC=seg_code[i];i=(i+1)%10; //i递增到10的时候,重新设为0_delay_ms(200);}}

    时间:2018-10-10 关键词: 数码管 avr单片机 proteus仿真

  • 关于proteus仿真的串口问题

    以下四幅图都是关于串口中断的问题,串口中断需要一个接收或者发送数据的触发。图一:因为由串口小助手发送的数据达到了单片机串口,所以引起了串口的中断。图二:图一的大图。图三:因为由串口小助手发送的数据达到了virtual terminal,没有到达串口,所以没有引起串口的中断。图四:图一和图三的综合,也不行main.c#include "os_cfg.h"#include "task0.h"#include "task1.h"#include "task2.h"#include "task3.h"void (* code task[])() = {task0,task1,task2,task3};void main(void){uchar i;os_timer0_init();os_timer1_init();EA = 1;//开总中断while(1){for(i=0;i

    时间:2018-10-09 关键词: proteus仿真 串口问题

  • 用proteus仿真C51时用到xdata时的问题

    在用proteus仿真做一个程序,但是51的内存资源太过稀有,使用到较大的数组的时候资源很快就耗尽了,这时需要用到xdata大模式下编译。然而在proteus下默认xdata是必须加上外扩ram才可运行的,需要对proteus下的单片机的数据内存位图设置,直接上图这样设置之后,单片机上加入大的数组也一样可以欢快的运行

    时间:2018-09-06 关键词: xdata c51时 proteus仿真

  • 51proteus仿真:生成正弦波

    仿真电路图和生成锯齿波的电路图一样。程序用中断来定时。C程序如下:#include sbit CS0=P3^0;sbit WR0=P3^1;bit flag=0;unsigned char i=0;unsigned char code sin_num[]={ 0,0,0,0,0,0,0,0,1,1,1,1,1,2,2,2, 2,3,3,4,4,4,5,5,6,6,7,7,8,8,9,9, 10,10,11,12,12,13,14,15,15,16,17,18,18,19,20,21, 22,23,24,25,25,26,27,28,29,30,31,32,34,35,36,37, 38,39,40,41,42,44,45,46,47,49,50,51,52,54,55,56, 57,59,60,61,63,64,66,67,68,70,71,73,74,75,77,78, 80,81,83,84,86,87,89,90,92,93,95,96,98,99,101,102, 104,106,107,109,110,112, 113,115,116,118,120,121,123,124,126,128, 129,131, 132,134,135, 137, 139,140,142,143,145,146,148, 149,151,153, 154,156,157,159,160,162,163,165, 166,168,169,171,172,174,175,177, 178,180,181, 182,184,185,187,188,189,191,192,194,195,196,198,199, 200,201,203,204,205,206,208,209,210,211,213,214,215,216,217,218, 219,220,221,223,224,225,226,227,228,229,230,230,231,232,233,234, 235,236,237,237,238,239,240,240,241,242,243,243,244,245,245,246, 246,247,247,248,248,249,249,250,250,251,251, 251,252,252,253,253, 253,253,254,254,254,254,254,255,255,255,255, 255,255,255,255,255 }; //这是正弦波上升半周期的采样void sinn()interrupt 1{ if(flag==0) { P2=sin_num[i++]; if(i==0){flag=1;i=255;} } else { P2=sin_num[i--]; if(i==255){flag=0;i=0;} }}main(){ TMOD=0X01; //计数器T0,自启动,定时,方式1 TH0=0xff; //选择计数器T0 TL0=0x00; IT0=1; //设置中断触发方式,下降沿 EA=1; //开中断 EX0=1;//外部中断INT0的,来扩展用可以按键调整波形 ET0=1; //外部中断INT0的,来扩展用可以按键调整波形 IP=0X01; //键盘中断级别高 TR0=1; CS0=0;//dac0832为直通方式 WR0=0; while(1) {}}

    时间:2018-09-05 关键词: 51 正弦波 proteus仿真

  • avr单片机proteus仿真第二课:流水灯

    先实现一个最简单的avr单片机proteus仿真,流水灯。对IO口写数据要先设置DDRxn=0xff,然后才输出PORTxn=输出数据。电路仿真图如下:avr c程序如下:#include #include int main(void){unsigned char i,j,k;DDRA=0xff;PORTA=0xff;for(;;){ for(k=0;k

    时间:2018-08-23 关键词: 流水灯 avr单片机 proteus仿真

  • 51proteus仿真:生成锯齿波

    之前做了一个adc0832的DA转换实验,利用adc0832把采集到的模拟信号(电压)转换成数字信号,输入到单片机,然后在7段数码管中显示出信号的电压来。所以这一次做一做数字转模拟的实验。51的比较多的数模转换实验是做信号发生器,锯齿波,正弦波,方波等。先做一做锯齿波吧。运放用的是标准运放opamp,主要是为了免去了解运放芯片参数的麻烦。程序如下:为了简单,我直接把dac0832设置为直通方式。实际运用的时候,直通方式是不能直接接单片机的。#include #include sbit CS0=P3^0;sbit WR0=P3^1;main(){ unsigned char k; WR0=0;CS0=0; while(1) { _nop_(); _nop_();for(k=255;k>0;k--){ P2=k; _nop_(); _nop_(); _nop_(); } }}

    时间:2018-08-09 关键词: 51 锯齿波 proteus仿真

  • proteus仿真之DS1302+LCD1602显示试验

    proteus仿真之DS1302+LCD1602显示试验仿真效果图为:C语言源程序如下:/*51单片机:DS1302+LCD1602 Proteus 仿真程序。功能:LCD1602时钟与日期的显示。仿真结果:LCD1602显示设定的时间与日期。*/#include /**********LCD1602接口程序**********/#defineLCD_PORTP1 //液晶LCD1602数据sbit RS = P2^4;sbit RW = P2^5;sbit E = P2^6;char data str1[16]="Date: ";char data str2[16]="Time: ";sbit SCK = P3^6; // DS1302时钟线sbit SDA = P3^4; // DS1302数据线sbit RST = P3^5; // DS1302复位线//DS1302 复位重定义#define RST_CLR RST=0//电平置低#define RST_SET RST=1//电平置高//DS1302 数据#define SDA_CLR SDA=0//电平置低#define SDA_SET SDA=1//电平置高#define SDA_RD SDA //电平读取//DS1302 时钟#define SCK_CLR SCK=0//时钟信号#define SCK_SET SCK=1//电平置高#define DS1302_SEC 0x80//秒数据地址#define DS1302_MIN 0x82//分数据地址#define DS1302_HOUR 0x84//时数据地址#define DS1302_DATE 0x86//日数据地址#define DS1302_MON 0x88//月数据地址#define DS1302_DAY 0x8a//星期数据地址#define DS1302_YEAR 0x8c//年数据地址#define DS1302_CTRL 0x8e//控制数据地址#define DS1302_CHARGE 0x90//涓流充电 bit ReadRTC_Flag; //读DS1302标志。1为读 0为不读。unsigned char time_buf1[8] = {40,14,2,16,23,59,50,7};// -年月日时分秒周 2014-02-14 10:59:50 7周unsigned char time_buf[8] ; // -年月日时分秒周void DS1302_Init(void);void DS1302_Write_Byte(unsigned char addr, unsigned char d);unsigned char DS1302_Read_Byte(unsigned char addr) ;void DS1302_Read_Time(void);void DS1302_Write_Time(void);void InitTIMER0(void);//inital timer0void Delay_1ms(unsigned char i);void Delay_10us(unsigned char i);void Write_Cmd(unsigned char cmd);void Write_Dat(unsigned char dat);void Addr_x_y(unsigned char x,bit y);void Show_Char(unsigned char x,bit y,unsigned char p);void Show_String(unsigned char x,bit y,char *ptr);void LCD_Init(void);void main(void) { LCD_Init();DS1302_Init(); DS1302_Write_Time();InitTIMER0();//P2=0xff; //51默认为输入while(1){if(ReadRTC_Flag==1){ReadRTC_Flag=0;DS1302_Read_Time();}str1[5]=time_buf1[1]/10 + '0';//年 数据的转换,str1[6]=time_buf1[1]%10 + '0';//因我们采用数码管0~9的显示,将数据分开str1[7]=0x2d; //加入"-"str1[8]=time_buf1[2]/10 + '0';//月str1[9]=time_buf1[2]%10 + '0';str1[10]=0x2d;str1[11]=time_buf1[3]/10 + '0';//日str1[12]=time_buf1[3]%10 + '0';str1[13]=0x20;str1[14]='W';str1[15]=time_buf1[7] + '0';//周几str2[5]=time_buf1[4]/10 + '0';//时 数据的转换,str2[6]=time_buf1[4]%10 + '0';//因我们采用数码管0~9的显示,将数据分开str2[7]=0x3a; //加入"-"str2[8]=time_buf1[5]/10 + '0';//分str2[9]=time_buf1[5]%10 + '0';str2[10]=0x3a;str2[11]=time_buf1[6]/10 + '0';//秒str2[12]=time_buf1[6]%10 + '0';Show_String(0,0,str1);Show_String(0,1,str2);} }/********************************/void Delay_1ms(unsigned char i) //最小延时1ms{unsigned char j;while(i--)for(j=0;j150usE=0;Delay_10us(4); //>25+10us}void Write_Dat(unsigned char dat) //写数据{Delay_10us(5);E=0;RS=1;RW=0;LCD_PORT = dat;Delay_10us(5);E=1;Delay_10us(5);E=0;Delay_10us(4);}void Addr_x_y(unsigned char x,bit y) //写坐标,定位置{unsigned char temp=0x80;//默认最高位:D7为1 即以0x80开始。 if(y) //y :0为第一行 1为第二行{temp"=0x40;}temp|=x;Write_Cmd(temp);}void Show_Char(unsigned char x,bit y,unsigned char p)//在指定位置显示一个字符。{Addr_x_y(x,y);Write_Dat(p);}void Show_String(unsigned char x,bit y,char *ptr){ unsigned char i;for (i=0;i> 1;}//写入数据:datfor (i = 0; i < 8; i ++) {if (dat & 0x01) {SDA_SET;}else {SDA_CLR;}SCK_SET;SCK_CLR;dat = dat >> 1;}RST_CLR; //停止DS1302总线}/*------------------------------------------------ 从DS1302读出一字节数据------------------------------------------------*/unsigned char DS1302_Read_Byte(unsigned char addr){unsigned char i;unsigned char temp;RST_SET;addr = addr | 0x01;//最低RD,有效为高电平for (i = 0; i < 8; i ++){if (addr & 0x01){SDA_SET;}else{SDA_CLR;}SCK_SET;SCK_CLR;addr = addr >> 1;}//输出数据:tempfor (i = 0; i < 8; i ++){temp = temp >> 1;if (SDA_RD){temp |= 0x80;}else{temp &= 0x7F;}SCK_SET;SCK_CLR;}RST_CLR; //停止DS1302总线return temp;}/*------------------------------------------------ 从DS1302读出时钟数据------------------------------------------------*/void DS1302_Read_Time(void) { unsigned char i,tmp;time_buf[1]=DS1302_Read_Byte(DS1302_YEAR);//年time_buf[2]=DS1302_Read_Byte(DS1302_MON);//月time_buf[3]=DS1302_Read_Byte(DS1302_DATE);//日time_buf[4]=DS1302_Read_Byte(DS1302_HOUR);//时time_buf[5]=DS1302_Read_Byte(DS1302_MIN);//分time_buf[6]=(DS1302_Read_Byte(DS1302_SEC))&0x7F;//秒time_buf[7]=DS1302_Read_Byte(DS1302_DAY);//周for(i=0;i

    时间:2018-08-08 关键词: lcd1602 ds1302 proteus仿真

  • 1~99秒倒计时数码管显示C程序+Proteus仿真

    1~99秒倒计时数码管显示C程序+Proteus仿真文件。优化了程序,使用51单片机内部定时器,可以实现1-99秒内倒计时。仿真效果为:源程序为:/*调试环境:Proteus 7.8AT89S52单片机8位共阴数码管功能为:实现数码管1秒~99秒倒计时, 12M晶振*/#include #define uchar unsigned charsbit LED1=P1^1; //连的是LED1#define MAX_NUM 13 //最大倒计时数1~99可设#define SEGPORT P0 //定义数码管连接端口sbit LE_DUAN = P2^0; //定义573锁存使能端口 段锁存sbit LE_WEI = P2^1; //定义573锁存使能端口 位锁存unsigned char code Seg_Duan[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //共阴数码管显示段码值 0~9unsigned char code Seg_Wei[] = {0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; //数码管的位码,低电平有效。static uchar second=MAX_NUM,count; //99只是一个数,可以任意改,因为这里只学习怎样实现倒计时uchar shiwei;uchar gewei;void delay(unsigned int cnt){ while(--cnt);}void main(){ TMOD"=0x01; //定时器设置 16位 TH0=(65536-50000)/256; //定时时间 50ms TL0=(65536-50000)%256; EA=1; ET0=1; TR0=1; SEGPORT = 0; LE_DUAN = 0; LE_WEI= 0; while(1) { shiwei=second/10; //数码管10位 gewei=second%10; //数码管个位 SEGPORT=0; //清空数据,防止有交替重影 LE_DUAN=1; //段锁存 LE_DUAN=0; delay(30); SEGPORT = Seg_Wei[1]; //先送位码值 LE_WEI = 1; //573高电平锁存 LE_WEI = 0; SEGPORT = Seg_Duan[shiwei]; //再送段码值,这里为 2~9 LE_DUAN = 1; //573高电平锁存 LE_DUAN = 0; delay(300); SEGPORT = Seg_Wei[0]; //先送位码值 LE_WEI = 1; //573高电平锁存 LE_WEI = 0; SEGPORT = Seg_Duan[gewei]; //再送段码值,这里为 2~9 LE_DUAN = 1; //573高电平锁存 LE_DUAN = 0; delay(300); }}void tim(void) interrupt 1 //定时器0中断 { TH0=(65536-50000)/256; //定时时间 50ms TL0=(65536-50000)%256; count++; if(count==20) //50毫秒定时,50*20=1000(毫秒)=1秒 { count=0; second--; if(second==0xff) /*无符号char型数值,0-1为:0xff,这里若为:0的话,则倒计到0时不显示0直接显示最大倒计数。*/ { LED1=~LED1; //这里让LED1反转一下,表现倒计时一周。 second=MAX_NUM; //回到最大倒计数值,再次倒计,当然,可以加入其他的控制, } }}

    时间:2018-08-03 关键词: 倒计时 数码管显示 proteus仿真

  • avr proteus仿真第一课:安装设置avr studio和winavr

    avr的开发环境需要安装两个软件:转载并修改一篇文章来说明这两个软件的安装设置吧WinAVR+AVR Studio 新手入门必读1.获得必须的软件请从Atmel官方获得最新版本的AVR Studio下载地址参见:http://www.cnblogs.com/proteus/archive/2011/11/09/2242583.html请从WinAVR官方获得最新版本的WinAVR下载地址:http://sourceforge.net/projects/winavr/files/WinAVR/注意:WinAVR和AVR Studio是2个不同的软件,前者是开源项目,不属于Atmel所有,后者是Atmel版权所有的。2.安装步骤1)安装WinAVR2)安装AVR Studio3)安装AVR Studio的Service Pack(如果有的话)3.新建测试工程1)启动AVR Studio2)选择"New Project"3)"Project type"里选择"AVR GCC",单击"Location"旁的按钮,选择工程保存位置(这里假设为C:),避免路径中有中文,(注意,确保工程保存位置没有中文路径,所以,不能保存在“我的文档”或者“桌面”之类含中文路径的)在"Project name:"里填入工程名test01,把"Create initial file"的钩去除,把"Create folder"钩上,单击"Next>>"4)"Debug platform:"里选择"AVR Simulator","Device:"里选择"Atmega128",单击"Finish"5)菜单File->New File,建立空白文档,复制以下代码到该文档中(注意:最后一个“}”下面还有一个空行):#include "avr/io.h"int main(void){ while(1);}6)菜单File->Save,在“另存为”对话框里选择工程保存的路径下工程名命名的文件夹下(这里假设为C:test01),你会看到已经有一个test01.aps文件存在了,那是AVR Studio的工程文件。“文件名”里填入“main.c”,保存。7)在"AVR GCC"工程管理窗格内的"Source Files"上单击右键,右键菜单里选择"Add Existing Source File(s)...",在"Add Source File"里选择刚刚建立的main.c文件。会看到工程管理窗格内的"Source Files"下多了个main.c文件。8)菜单Project->Configuration Oprions,在"General"下(默认就是),确认"Use External MakeFile"没有钩上, "Frequency:"填入频率“8000000”,"Optimiztion"选择"-00",确认"Create Hex File"已经钩上,然后单击确定(请勿修改其它设置)9)菜单Build->ReBuild All,编译工程。如果操作正确,应该没有警告和错误。10)菜单Debug->Start Debugging,顺利的话,软件仿真已经启动。11)至此,测试工程已成功。可以在工程保存目录下看到一个default文件夹,打开后有test01.elf(AVR Studio的支持的仿真调试文件格式之一),test01.hex(烧写时要用的文件)成功的显示:Build started 9.11.2011 at 16:14:41avr-gcc -mmcu=atmega128 -Wl,-Map=liaojie.map main.o -o liaojie.elfavr-objcopy -O ihex -R .eeprom -R .fuse -R .lock -R .signature liaojie.elf liaojie.hexavr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 --no-change-warnings -O ihex liaojie.elf liaojie.eep || exit 0avr-objdump -h -S liaojie.elf > liaojie.lssAVR Memory Usage----------------Device: atmega128Program: 204 bytes (0.2% Full)(.text + .data + .bootloader)Data: 0 bytes (0.0% Full)(.data + .bss + .noinit)Build succeeded with 0 Warnings...4.给新手的建议:如果书中/资料中以命令行方式编译文件,请跳过这些例子中的命令行操作,改为用AVR Studio新建工程来编译。如果有Makefile方面的讲解,也请跳过。因为这些讲解可能太过于简略,而难以理解。1)不要去用WinAVR带的mfile所产生的Makefile文件,只使用AVR Studio菜单Project->Configuration Oprions来配置工程,(不要钩上"Use External MakeFile")2)工程保存路径中不要有中文名,即只在英文名文件夹下(包括其上各级文件夹也是英文)3)始终使用Build->ReBuild All,编译工程4)新建工程时,工程名不要用Makefile(不论何种大小写组合)5)新建工程时,不要钩上"Create initial file"6)不要修改"Output File"里的文件名7)现在,中断程序是以ISR(...)方式声明的,书和资料可能落后于WinAVR的更改,请随时通过开始菜单里WinAVR下的avr-libc Manual [WinAVR]查看目前WinAVR的各种函数和头文件说明5.进一步学习:当你比较熟悉用AVR Studio完成你的工程编译过程后,可以考虑学习Makefile

    时间:2018-08-01 关键词: AVR studio r winavr proteus仿真

  • proteus仿真之8位数码管动态扫描显示试验

    /*Proteus 仿真之8位共阴数码管动态扫描实验*/程序:/*Proteus 仿真之8位共阴数码管动态扫描实验*/#include#define SegPort P0 //定义数码管连接端口sbit LE_Duan= P2^0; //定义573锁存使能端口 段锁存sbit LE_Wei= P2^1; //定义573锁存使能端口 位锁存unsigned char code Seg_Duan[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; // 数码管显示段码值 0~9unsigned char code Seg_Wei[] = {0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; //数码管的位码,低电平有效。/*简单延时程序*/void delay(unsigned int cnt){while(cnt--);}void main(void){unsigned char i=0;while(1){for(i=0;i

    时间:2018-07-10 关键词: 数码管 动态扫描 proteus仿真

  • Proteus在单片机教学和科技制作中的应用与实践

    Proteus在单片机教学和科技制作中的应用与实践

    随着计算机的高速发展,大量EDA软件被引入电子类专业的课程教学中。例如在电路分析、模拟电子技术和数字电子技术课程中经常把EWB仿真软件引入到教学中以提高教学质量。同样,在单片机的领域里也有功能强大的EDA软件可以作为教学的辅助手段。本文将Proteus仿真软件引入到单片机课程的教学改革中,取得了较好的效果。1 单片机课程现状1.1 单片机课程的重要性单片机课程是自动化、嵌入式等工科专业的一门专业方向课,目的是培养实际动手能力强的高技能型人才。掌握单片机基础知识,具备基本应用技能,才能符合当前社会对自动化、嵌入式专业人才的要求。同时,单片机教学的效果对后续课程的学习和专业技能的掌握也具有重要意义。作为一门应用性极强的课程,教师不仅要在理论课上下功夫,还必须在实验实践课积极做出探索,充分利用身边资源,结合现代计算机技术,提高该课程的教学质量。1.2 传统单片机教学存在的问题1.2.1 理论教学存在的问题由于单片机课程本身比较抽象,所以在教学中必须把教学内容更直观地展示给学生。把实验板或者仿真器引入到课堂上进行演示实验。但采用这种方法往往效果不是很好。一方面教师在课堂上做演示很浪费时间,降低了教学的效率;另一方面小小的实验板和仿真器演示起来很难让所有学生都观察到效果。1.2.2 实践教学存在的问题实验课是本课程重要的教学环节,其目的是提高学生的动手能力和分析、解决问题的能力,使学生能熟练应用单片机的集成环境和开发系统,进行单片机应用系统设计,为今后进一步设计与应用单片机打下扎实的基础。以往实践教学通常在单片机实验室进行,学生使用高度集成化的实验箱完成老师布置的实验任务,学生每次实验用到的只是实验箱的固定模块,只要简单地连接几根导线、输入相关程序就能完成该次实验,学生搞不清楚硬件原理及设计步骤,失去了分析问题、解决问题的机会,硬件设计的能力得不到很好提高。因而,对单片机实验课进行教学改革势在必行。2 Proteus仿真软件介绍Proteus仿真软件是目前较先进、完整的嵌入式系统设计与仿真平台软件。它可以方便地安装在普通PC机上,与Keil C软件共同构建起个人的单片机虚拟仿真实验室。Proteus内含6 000种模拟和数字器件模型,功能强大,具体如下:(1)用于数字、模拟电路及单片机应用系统等原理图的绘制;(2)对数字、模拟电路及单片机应用系统进行分析与仿真; (3)利用自动布线或人工布线将原理图转换为PCB图。Proteus软件与其他EDA软件相比,具有革命性的特点:(1)用户可采用诸如LED/LCD、键盘、RS232终端等动态外设模型对设计进行交互仿真; (2)仿真处理器及其外围电路,并配合显示及输出,能直观看到运行后输入输出的效果。3 Proteus在单片机课堂教学中的应用为了解决单片机课程理论教学中存在的问题,将Proteus仿真软件应用到课堂教学中,利用仿真的形象、生动、实在等特性,对单片机课程理论教学产生积极的影响,是其他教学手段难以替代的。3.1预先案例设计 现场效果演示利用Proteus仿真软件预先设计大量的单片机应用实例,课堂上,用Proteus软件向学生演示单片机软硬件设计开发、调试的全过程,并观察硬件的工作和程序执行效果,使学生通过实例对单片机的工作原理、工作过程、工作效果有更多的了解,对提高学生的学习兴趣和学习积极性有非常大的帮助。图1为电子时钟课程实例的仿真及效果演示图。3.2合理布置作业 拓展学生思维对理论课中的重点内容,合理地布置作业,让学生利用Proteus来验证作业,不仅可以让学生思维得到扩展,还可让学生的动手能力得到一定的提高。以图1所示的电路为例,要求学生在图1的基础上添加独立键盘K0~K2做输入设备,通过软件编程设计并实现一个可调的电子时钟,要求如下:(1) K0作为时钟调节的菜单键,第一次按下K0秒钟处闪烁并时钟停止,提示可以调节时间秒;第二次按下分钟处闪烁,提示可以调节时间分;第三次按下时钟处闪烁,提示可以调节时;第四次按下退出调时菜单,时钟开始继续走动;(2) K1和K2分别是时分秒调节的加减键。只有当菜单键按到相应的时分秒时,才可使用K1和K2来加减调节。图2为调节时间分时的可调电子时钟课程实例的仿真图及效果演示图。4 Proteus在实践教学中的应用在实践教学环节中,在以下几个方面进行了教学方法和教学手段的改革。4.1常规实验加强理论基础知识的掌握在实践教学环节中引入Proteus仿真软件,学生可根据实验内容的要求,在Proteus元件库中选择所需要的虚拟元件设计应用电路,这样,学生不仅可以调试自己编写的程序,而且可以形象、直观地看到程序执行效果并且能锻炼硬件电路的设计能力。虽然引入Proteus仿真软件对学生动手能力的提高有一定帮助,但为了尽量避免学生淡化对基本技能训练的重视程度、忽视规范掌握仪器操作等弊端,在实际的教学过程中采用了虚实互补的原则安排教学,仿真完成后要求学生利用实验室中的集成试验箱进行最后的硬件连接与调试。4.2 增加综合开放性实验拓展综合思维为了提高学生独立分析和解决工程实际问题的能力,让学生具备独立开发单片机应用系统的技能,专门开设了单片机综合课程设计,题目由老师推荐或学生自荐。先让学生组队自己设计方案,了解并选用电子元器件,在计算机上进行仿真设计,然后到电子市场购买元器件最后进行硬件设计与调试。使学生了解从选题、调研、制定设计方案、采购元器件、软硬件设计、线路焊接、调试检测等整个设计调试过程,从而进一步提高了学生自主开发和实际动手能力及兴趣。另外,这种先仿真后实物的制作,不仅大大降低了系统开发的周期,而且降低了硬件电路制作的损耗。4.3科技制作提升创新能力课程设计、毕业设计、各种竞赛是学生走向就业的重要实践环节。在各种科技制作活动中,学生利用Proteus仿真软件进行仿真实现后,再进行硬件的设计和调试,这样不仅可以避免由于设计上的错误所造成的硬件投入上的浪费,而且可以缩短学生完成大型设计的时间。

    时间:2018-06-21 关键词: 嵌入式处理器 eda软件 单片机课堂教学 proteus仿真

  • ADC0832程序完整版源码+Proteus仿真

    前段时间一直在为ADC0832的程序感到疑惑,从网上找了很多的代码,用Proteus仿真,最后都出现了一些奇怪的问题,有的根本没法读取数据,有的数据有错误。 当参考电压为5V时,如果把输入电压从0一直调到5V,读取的数据应该是从0到255,2.5V时应该是128。但是我发现一些源码在输入0~2.5V时读取出来的是0~255,到2.5V时读取的数据为0,从2.5到5V,读出的值又从0增加到255,始终不正确。今天下午特地查阅的ADC0832英文原版的DataSheet,又参考了一篇中文文档,终于写出了其完整的程序,并且先后读取了MSB FIRST DATA和LSB FIRST DATA,进行比较,如果两个数据相等,返回读取的数据,否则返回0,这样可以避免读取发生错误,更稳定可靠。并通过了Proteus仿真。 下图是ADC0832的时序图: 其中T-SetUp为250ns,由于使用的是51单片机,晶振11.0592MHz,机器周期比这个值大,可以不考虑,但为了防止出现异常,还是延时了两个机器周期。注意在第11个时钟下降沿之后,DO上的电平既是MSB FIRST输出的最后一位,又是LSB FIRST输出的第一位。以下是读取ADC0832的代码。 [cpp] view plain copysbit CS_0832 = P1^0; sbit CLK_0832 = P1^1; sbit DO_0832 = P1^2; // DI、DO不同时有效,可共用一个接口 sbit DI_0832 = P1^2; extern void _nop_ ( void ); #define pulse0832() _nop_();_nop_();CLK_0832=1;_nop_();_nop_();CLK_0832=0 //把模拟电压值转换成8位二进制数并返回 unsigned char read0832() { unsigned char i, ch = 0, ch1 = 0; CS_0832=0; // 片选,DO为高阻态 DI_0832=1; // 此处暂停T-SetUp: 250ns (由pulse0832完成) pulse0832(); // 第一个脉冲,起始位,DI置高 DI_0832=1; pulse0832(); // 第二个脉冲,DI=1表示双通道单极性输入 DI_0832=1; pulse0832(); // 第三个脉冲,DI=1表示选择通道1(CH2) // 51单片机为准双向IO口:应先写入1再读取 DI_0832=1; // MSB FIRST DATA for(i = 0; i < 8; ++i) { pulse0832(); ch <<= 1; if(DO_0832==1) ch |= 0x01; } // MSB FIRST输出的最后一位与LSB FIRST输出的第一位是在 // 同一个时钟下降沿之后,故此处先执行读取,后执行pulse // LSB FIRST DATA for(i = 0; i < 8; ++i) { ch1 >>= 1; if(DO_0832==1) ch1 |= 0x80; pulse0832(); } CS_0832=1; // 取消片选,一个转换周期结束 return (ch==ch1) ? ch : 0; // 返回转换结果 }

    时间:2017-08-09 关键词: adc0832 proteus仿真

  • 红外遥控发射器Proteus仿真研究

     0 引言 红外遥控在家电、玩具、工控、智能仪表中是使用最广泛的一种通信和遥控手段。Proteus仿真能大大加快该遥控系统的开发周期和提高其性能,但是当前版本的Proteus中尚没有红外发射器的仿真元器件,只有一个IRLINK模块可以用于接收并解调红外信号,给红外系统仿真带来了较大的难度。目前学者对红外遥控系统的接收部分仿真已经有较多的研究,但是还很少有针对红外遥控发射部分的典型仿真研究。可以设计一种典型的红外发射器仿真模块,该模块在仿真中相当于实际的遥控器。进行红外遥控系统开发仿真时,可以将此模块用于红外遥控接收电路以及其软件的快速验证,加快产品开发周期。 1 红外遥控发射器调制解调过程简介 红外遥控发射器发射的一帧数据一般由引导码、低8位用户编码、8位数据码、8位数据码的反码等4部分组成。其中用户识别码能区别不同的红外遥控设备,防止不同机种遥控码互相干扰。后16位为8位数据码和8位数据码的反码,每次8位的数据码被传送之后,它的反码也随即被传送,用于确保接收数据准确。这种遥控码是采用脉冲宽度调制方式,它的特征是:采用脉宽调制的串行码,以脉宽为0.565ms、间隔0.56ms、周期为1.125ms的组合表示二进制的“0”;以脉宽为0.565ms、间隔1.685ms、周期为2.25ms的组合表示二进制的“1”。 红外数据帧经编码后,还要用38kHz的方波进行脉冲幅度调制。如图1所示,最上面一行为待发射数据的波形,第二行为38k载波,第三行为经载波调制后的红外发射信号波形,第四行是经过一种专门的红外接收滤波后的数据还原。可以看出,最后通过解码还原出来的数据波形与红外遥控器发射的数据波形相位刚好反向。 2 红外遥控仿真硬件电路设计 图2所示是红外发射接收一体化仿真电路。单片机U2部分为红外接收,并显示接收到的红外编码,显示部分可采用数码管,LCD等显示器件,学者已经对红外接收及显示有较详细的研究,在此不作论述,只用作验证红外遥控发射器模块的有效性。 单片机U1部分为模拟红外遥控器发射。因Proteus仿真软件里面没有常见的红外遥控发射器处理芯片,这里用8051单片机U1来实现,其P3.4口输出待发射数据,该数据经与门U3和38k载波信号调制后发射到接收电路,接收电路再通过Proteus软件自带的IRLINK模块解调后送到U2的外部中断INT0。遥控发射器按键输入采用4×4矩阵键盘,当按下某一个键后会发出对应的编码。例如按下键K6,按照红外发射数据帧结构,将通过P3.4口串行发送“00,00,0x06,0xf9”,其中,前面的“00,00”为用户码,对于不同的设备需作相应的修改;“0x06”是代表6号键,“0xf9”是“0x06”的反码,用于校验,提高传输准确性。只要在单片机的程序中对用户码和按键编码作相应的修改,就能使该遥控发射器在各类红外遥控系统仿真中通用。 3 红外遥控发射器程序设计 3.1 软件功能概述 根据仿真硬件电路设计,单片机的软件程序需要完成以下2个功能:1)按键扫描:实时对4×4矩阵键盘扫描,得到按键码,并根据按键码查找出对应的红外发射编码。2)编码发射:根据前述2.1和2.2的编码协议通过P3.4口发射红外编码。 单片机程序功能较简单,但是对于按键扫描和编码发射的时序要求较高,既要保证实时扫描到按键,又要保证红外编码的实时发射。 3. 2 程序设计 程序流程图如图3所示,在时序上,整个程序基本上所有的时间都是在调用键盘扫描子程序,因此能检测到任何时候的按键。只有在扫描到有按键时才会调用发射红外编码程序,发射一次红外编码程序耗时为58.5ms至76.5ms,该时间很短,对于按键时序不会产生任何影响。 发射红外编码采用定时器中断的方式来实现,设定时值为38k,也就是每隔26 μs中断一次。这样,要发送9ms的引导码,只需要将P3.4置为1,并控制定时器中断次数为346次即可。同样,要发送4.5ms的起始码,只需要将P3.4清0,并控制定时器中断次数为173次即可。其它部分类似。得到的红外编码数据发送子程序如下: 在红外编码数据发送子程序中,“IR_data[]”数组里存放的是一帧数据的4个编码,每个编码8位,共32位;“endcount”用于控制定时时间,例如“endcount=346;”指令将控制发送9ms的起始码。 4 仿真及实物验证 4. 1 仿真结果 红外遥控发射数据时的仿真波形图如图4所示:第一个波形为由单片机U1的P3.4口发送出来的数据,第二个波形为38k载波,第三个波形为调制后的红外发射信号,第四个波形为红外接收滤波后的数据还原。可以看出还原后的数据波形与发射出的数据波形相位刚好反向。这种红外遥控码波形与前述遥控器厂家提供的如图1所示的数据完全吻合。 4.2 实物验证结果 图5所示为用实物验证模拟红外发射接收。其中(b)部分为接收红外遥控信号,解调并用两位数码管来显示接收到的红外编码。(b)部分的解调和显示程序是事先经海信电视CN-22601遥控器、开博尔电视盒遥控器、志高空调ZH/JT-06遥控器等三款红外遥控器测试通过的,可以确保解调和显示程序是正确的。(a)部分为模拟红外遥控发射数据。(a)和(b)两部分通过两根线相连,白色的一根是地线,使两块电路板共地;红色的一根连接(a)部分的P3.4口和(b)部分的外部中断INT0。图5中显示的是当(a)部分按下按键“K14”时,(b)部分显示“14”。 实验结果证明,仿真结果在实物电路板上同样是正确的,说明此发射模块就等同于一个实际的遥控器。 5 结论 红外遥控发射器Proteus仿真模块具有结构简单、可靠性高、可移植性强等优点。本模块填补了Proteus仿真软件对于红外遥控发射器件的空白。借助本模块,红外遥控系统开发者能大幅度地缩短产品的开发时间,大大提高工作效率。

    时间:2015-01-02 关键词: 红外遥控 发射器 单片机 proteus仿真

  • 总线式原油盘库数据采集子系统的设计

     摘要:目前胜利油田滨南采油厂原油盘库系统的自动化程度较低。为大力提高其自动化水平,本文根据该采油厂各联合站分散采集、集中监视的特点,设计了基于RS-485总线和主从单片机结构的数据采集子系统方案。由位于监控室的主单片机作为中枢,通过RS-485总线采集各从单片机收集到的原油参数并通过串口上传到上位机中。利用上位机软件配合Proteus软件和Keil软件对整个子系统进行了仿真和测试,从而验证了其可行性。 在采油厂联合站中对原油的液位、油水界面、密度、含水、库存量等各项参数的计量过程就是盘库。盘库是原油生产过程中的一项重要工作,只有精确掌握了各项生产数据才能做出更好的生产及销售决策。这是一项关系到企业发展和经济效益的重要任务,因此,研究与开发一套现代化的原油自动盘库系统是非常必要的。滨南采油厂是胜利油田位于山东省滨州市的一个重要采油厂,但受限于当时的技术与资金等方面的因素,该厂现在使用的盘库系统自动化程度不高,突出表现在源头数据的采集与传输必须以人工的方式完成,费时劳力,已经满足不了现代化、高效率、高精度的生产要求。本文就是以滨南采油厂为背景,在其实际应用盘库系统的基础上,参考了国内外一些油田联合站的盘库方案,设计开发了一套基于RS-485总线和主从单片机结构的原油自动化盘库数据采集子系统。 1 研究背景 滨南采油厂现有的原油盘库系统是以基于浏览器和客户端软件的方式进行原油生产数据的采集、传输及处理。首先通过人工读取的方式获得原油罐上测量仪表或其他计量工具测量得到的数据,然后生产单位用浏览器将原油生产数据录入数据库,之后计划科工作人员用客户端软件对原油生产数据进行统计以供全厂人员查询。 该系统由5部分组成,第一部分为原油生产数据录入部分,由各矿区和集输大队的工作人员以浏览器的方式将数据录入到服务器中;第二部分为原油生产数据统计部分,计划科工作人员每天通过客户端软件对各单位上报数据进行统计,形成每天的产量数据;第三部分为原油生产数据查询部分,供全厂各部门以浏览器方式查询生产数据;第四和第五部分分别是原油生产数据报表输出和系统维护部分,供计划科人员使用,以客户端软件的形式实现。 现有系统到目前为止已建成十余年,一直运行稳定。但其整体自动化程度亟待提高,集中表现在源头数据的采集和传输只能依靠人工完成。若能实现源头数据的自动采集和传输,即可完成现有盘库系统中第一部分(即:生产数据录入部分)的升级代替,并能与现有盘库系统中的其余部分实现良好衔接,从而可将滨南采油厂原油盘库系统的自动化水平提高到较高水平。 2 需求分析及测量方法 针对滨南采油厂现在实际运行的盘库系统由人工完成数据采集的现状,需做出以下几方面的改进:利用传感器技术实现源头数据的自动采集,提高数据采样频率,实现数据自动存储、显示与上传,实现数据的远程实时监控。 为实现盘库数据的自动采集,经多方比较,针对不同类型油罐采用了如下测量方法。 2.1 针对沉降罐的测量方法 沉降罐的特点是原油含水率较高,且随着高度的不同含水率变化较大,且一般不是线性关系。因此,应测量出不同高度处的含水率并进行平均。为此,先用超声波液位变送器测量出油水混合物的液位,然后使用智能采集装置测量出不同高度处的含水率与温度。智能采集装置的主要工作部件是一个装有短波发生器及接收器的移动探头。当油水混合物的含水率变化时,其对能量的吸收也会相应变化,这种表现会被接收装置记录下来并转换成适宜单片机接收的标准信号。 具体工作过程是让移动探头先运行至油罐最底部,然后在油罐中自下而上采集不同高度处的含水率,并将含水率为95%的位置处定义为油水界面。此后,让探头继续等间隔上升,测量出油层不同高度处的含水率及温度,直至液面的顶端。该方案的整体结构如图1所示。 根据上述测量原理,沉降罐中原油储量的计算公式为: 其中,ρo和ρw分别是水和原油的密度,并且需要做温度修正。 2.2 针对净油罐的测量方法 净油罐中原油的特点是含水率较低,通常来油的含水率已经低于5%,经净油罐再次沉降后甚至可达1%以下。并且,净油罐中的含水率随油层高度变化不大,因此可用外输原油的含水率来代替油罐中的含水率。这样,只需使用射频导纳界面仪和超声波液位变送器分别测出油水界面的高度和液位就可以计算出油罐中的储油量了。计算公式为: 其中,H为油层的高度,即液位减去油水界面高度。 2.3 针对外输管道的测量方法 通过安装高精度的含水分析仪、在线密度计和流量变送器可实现计量。具体计算公式为: G=Viρ[MfCpCt(1-Cω)] (4) 其中,Vt为流量计测得的总流量,Mf为流量修正系数,Cp为原油压力修正系数,Ct为原油温度修正系数。 3 总体设计 该系统由3层结构组成,最底层是现场数据采集层,负责对传感器采集到的数据进行调理与转换;中间层是数据传输层,负责数据的本地存储与传输;最上层是数据存储与界面层,负责将采集到的数据存储到上位机的数据库中,并实现与工作人员的人机对话,可显示即时及历史数据、绘制统计图、输出报表及打印、设置系统参数、执行远程手动控制等。 系统工作过程为:由安装在各类油罐上的各种功能的传感器将采集到的生产数据如液位、油水界面高度、原油含水率和温度等信息经信号调理、模数转换后,传送到安装在油罐附近的现场单片机即从单片机上,然后利用RS-485总线通过串口传送到主单片机中,最后经电平转换将采集到的数据发送到上位机,在上位机中进行数据的运算、存储与显示。 系统总体结构图如图2所示。 4 系统硬件设计 硬件部分主要由主/从单片机最小系统、串口复用电路、RS-485通信电路、数据存储电路、模数转换电路等组成,系统硬件结构图如图3所示。 为节约成本,本系统中使用的单片机均为51单片机。所使用的时钟均为内部方式,即在XTAL1和XTAL2两端外接石英晶体作定时元件,内部反相放大器自激振荡产生时钟,时钟频率为11.059 2 MHz。复位方式采用手动复位。 51单片机仅有一个串口,而主单片机与上位机和与从单片机的通信均是通过串口进行,因此涉及到串口复用。文中串口复用电路就是实现这个功能,具体是使用两片多路模拟开关4051分别实现单片机读写数据的方向选择,另外使用两个控制端口进行通路的选通。 主从单片机之间的通信是基于RS-485总线来实现的,总线拓扑结构采用终端匹配的总线型结构,首尾两端使用的阻抗匹配电阻为120Ω。通信协议采用的是Modbus中的RTU模式,通信方式为主从式,仅有一个主机,各从机有唯一编号,且从机间不能相互通信。 由于要在现场单片机进行数据备份,防止总线故障时出现数据丢失,因此要在从单片机电路上扩展外部数据存储器。经容量测算,选用6264静态RAM进行了扩展,并用一片74LS373进行数据锁存。 A/D转换器采用MCP3204,这是由Microchip公司生产的4通道、12位微功耗串行模数转换器。4个通道分别用于采集液位、油水界面、含水及温度,其他量可在上位机上计算得出。12位模数转换器的精度可达0.2‰,完全可满足需要。 5 系统软件设计 软件设计采用模块化结构。单片机程序使用C语言开发,开发环境为Keil μVision4。上位机程序使用VB6.0进行开发。 系统软件设计包括主单片机程序设计、从单片机程序设计以及上位机程序设计3部分,其结构框图如图4所示。其主要功能模块的作用如下: 串行通信模块用来实现主从单片机间的通信以及主单片机与上位机间的通信;定时器模块用来设置串行口波特率以及RS-485通信协议中的帧定时和字节定时;模数转换模块用于对传感器采集的数据进行AD转换。上位机程序中的数据处理与显示模块用于对主单片机上传的数据进行处理、显示并将结果存储到数据库中。 主单片机和从单片机主程序的流程图分别如图5和图6所示。 上位机的主要功能是定时唤醒主单片机,并向其发送数据采集命令,然后等待接收数据,最后将数据实时显示并存储。其主程序的流程图如图7所示。 6 仿真实现 本文中主、从单片机的数据采集与通信部分均通过Proteus软件进行了仿真实现。上位机软件与Proteus软件之间通过虚拟串口进行相互通信。图8给出了主单片机上LCD的显示结果,对应当前采集过程中3个油罐的液位和油水界面高度。图9为上位机上的显示结果,给出了本次采集的时间以及3个油罐中所有生产数据等信息。 7 结论 文中为实现滨南采油厂各联合站生产数据的自动采集、传输、存储与显示,设计了一套原油盘库数据采集子系统。该子系统采用主、从单片机结构,利用RS-485总线进行数据传输,并最终上传到联合站主控室上位机的数据库中。 利用Proteus、Keil和上位机软件进行了联合仿真与调试,验证了方案的可行性,值得在采油厂中应用。该方案具体实施后,将实现对滨南采油厂现有盘库系统中人工录入数据部分的升级代替,并能与现有盘库系统中的其余部分实现良好衔接,从而可将该厂原油盘库系统的自动化水平提高到较高水平。

    时间:2014-05-19 关键词: 单片机 rs-485总线 原油盘库系统 proteus仿真

发布文章

技术子站

更多

项目外包