Protues-ATmega8仿真
- 格式:pdf
- 大小:2.57 MB
- 文档页数:61
第五讲定时/计数器的学习提要:主要学习ATmega8的T/C0、T/C1和T/C2三个定时/计数器的应用。
前面我们学习了ATmega8的通用I/O口的应用和外部中断的应用,相信你一定会觉得自己进步很快吧。
好了接下来我们就进行定时/计数器的学习:5.1 ATmega8定时/计数器的特点:ATmega8共有3个定时/计数器:Timer/Counter0—8bit、Timer/Counter1—16bit 和Timer/Counter2—8bit。
这三个定时/计数器除了能够实现通常的定时和计数功能外,还具有捕捉、比较、脉宽调制(PWM)输出、实时时钟计数等功能。
5.2 8位定时/计数器0—T/C0介绍T/C0主要有一下特点:1. 8bit字长,最大可计数0xFF;2. 单通道计数器;3. 外部事件计数;4. 频率发生器;5. 带10位预定比例分频器。
学习应用T/C0之前我们首先要了解几个相关的寄存器:TCCR0、TCNT0、TIMSK和TIFR。
一.T/C0控制寄存器TCCR0的[2:0]位CS0[2:0]:时钟源选择。
CS02 CS01CS00 说明0 0 0 无时钟源,停止T/C00 0 1 系统时钟0 1 0 CLKio/8来自预分频器0 1 1 CLKio/64来自预分频器1 0 0 CLKio/256来自预分频器1 0 1 CLKio/1024来自预分频器1 1 0 外部T0脚,下降沿驱动1 1 1 外部T0脚,上升沿驱动对该寄存器的理解可以与INT0的MCUCR作类比,那里是选择外部中断的触发方式,这里是选择T/C0的时钟源。
另外这里作几点说明:A 当时钟源选择系统时钟时,系统内部时钟直接作为T/C0的时钟源,这是最高频率的时钟源。
B 选择预分频器作时钟源,预定分频器对系统时钟CLKio按四个不同的分频比例分频,输出4个不同周期的时钟信号CLKio/8、CLKio/64、CLKio/256、CLKio/1024。
[整理版]proteus仿真单片机实例用器和存储器、断点和单步模式Proteus一部分是智能原理图输入系统引言Keil C51 运行可提供单片机体积小Proteus进行编译,编译成功后生成30的多种元件库,超过 ISIS,重量轻,进入仿真软件的主界面,如图等多种系列的处理器。
IAR C-SPY,Keil,具有很强的灵活性而且价格便宜,具有逻辑判断,定时计数等多ISIS(Intelligent Schematic Input System)8000data.hex,也可以仿真模拟数字混合电路。
种模拟、数字元器件。
可以按照设计的要求选择、MPLAB文件。
Protues 等开发工具的源程序进行调试的功包含强大的调试工具,具有对寄存1 所示。
主界面分为菜单栏,工具3.2 绘制电路图,编写和虚拟系统模型 data.c文件,能;能够观察代码在仿真硬件上的实时运行效果;对显示,按钮,键盘等外设的交互可视化不同生产厂家的元器件。
此外,对于元器件库中没有的元件,设计者也可以通过软件自己创VSM(Virtual Model System)利栏,模型显示窗口,模型选择区,元件列表区等。
种功能,广泛应用于仪器仪表,家用电器,医用设备的智能化管理和过程控制等领域。
以单;另一部分是高级布线及编辑软件 ARES(Adv-Ancd Routing 进行仿真。
建。
,nd Editing Software) 片机为核心的嵌入式系统已经成为目前电子设计最活跃的领域之一。
在嵌入式系统的中,开除拥有丰富的元器件外, 2.2 Proteus PCB 也就是PCB. ProteusProteus 2.1 Proteus VSM还提供了各种虚拟仪器,如常用的电流表,电压表,的PCB设计除了有自动布线仿真功能外,还集成了的仿真 Proteus可以仿真模拟电路及发板成本高,特别是对于大量的初学者而言,还可能由于设计的错误导致开发板损坏。
利用示波器,计数数字电路PCB设计,支持多达/定时/频率计,16个布线层,可以任意角度放置元件和焊接连线;集成了高智能的布线算法,可以方便地进行SPI调试器等虚拟终端。
Protues仿真赛DA模块(DAC0832)实例程序(实现0到255八位二进制的模拟电压转换)#include "reg51.h"#define uchar unsigned char#define uint unsigned int#define out P1sbitdac_cs=P2^0;sbitdac_wr=P2^1;void main(){uchar i=0,k=100;while(1){out=i;dac_cs=0;dac_wr=0;dac_cs=1;dac_wr=1;i++;if(i>255)i=0;while(--k);}}ADC0804模块与红外测距传感器GP2D12实例程序(将红外测距显示的距离化成P1口的八位二进制)uint adc0804()//adc0804读取数据并送入P1口,read=1991/(read+3)-7为距离传感器的计算公式{wr = 0;read = P1;delayms(10);wr=1;delayms(10);read=1991/(read+3)-7;return read;}LCD1602模块初始化#include<reg51.h>#include<intrins.h>#define uint unsigned int#define uchar unsigned charsbit LCD_RS=P2^0; //lcd1602数据、命令选择端sbit LCD_EN=P2^2; //lcd1602使能线void LCD_init(void) //LCD初始化{LCD_EN=0;write_cmd(0x38);write_cmd(0x0c);write_cmd(0x06);write_cmd(0x01);}void write_cmd(uchar com) //写命令到LCD{LCD_RS=0;P0=com;delayms(5);LCD_EN=1;delayms(5);LCD_EN=0;}void write_data(uchardat) //写显示数据到LCD {LCD_RS=1;P0=dat;delayms(5);LCD_EN=1;delayms(5);LCD_EN=0;}void LCD_pos(ucharx,uchar y) //显示地址{ ucharpos;switch(x){case 0:x=0x80;break;case 1:x=0xc0;break;}pos=x+y;write_cmd(pos);}DS18B20温度传感器程序/*--------------精确延时5us子程序---------*/ void delay5(uchar n){do{_nop_();_nop_();_nop_();n--;}while(n);}/*--------------初始化函数--------------------*/ void init_ds18b20(void){uchar x=0;DQ =0;delay5(120);DQ =1;delay5(16);delay5(80);}/*--------------读取一字节函数----------------*/ ucharreadbyte(void){uchar i=0;uchar date=0;for (i=8;i>0;i--){DQ =0;delay5(1);DQ =1; //15微秒内拉释放总线date>>=1;if(DQ)date|=0x80;delay5(11);}return(date);}/*--------------写一字节函数------------------*/ voidwritebyte(uchardat){uchar i=0;for(i=8;i>0;i--){DQ =0;DQ =dat&0x01;//写"1" 在15微秒内拉低delay5(12); //写"0" 拉低60微秒DQ = 1;dat>>=1;delay5(5);}}/*--------------读取温度函数------------------*/ ucharretemp(void){uchara,b,tt;uint t;init_ds18b20();writebyte(0xCC);writebyte(0x44);init_ds18b20();writebyte(0xCC);writebyte(0xBE);a=readbyte();b=readbyte();t=b;t<<=8;t=t|a;tt=t*0.0625;return(tt);}定时器简单仿真与程序(控制P1^0口输出10Hz到2KHz的可调方波)void timer0() interrupt 1{TH0=X1;TL0=X2;OUTPUT=~OUTPUT;}void int0_ser(void) interrupt 0{FREQ=FREQ+10;X1=(uint)(65536-(double)(500000/(1.020*FREQ)))/256; //定时器初值计算X2=(uint)(65536-(double)(500000/(1.020*FREQ)))%256;TR0=1;}void int1_ser(void) interrupt 2{FREQ=FREQ-10;X1=(uint)(65536-(double)(500000/(1.020*FREQ)))/256; //定时器初值计算X2=(uint)(65536-(double)(500000/(1.020*FREQ)))%256;TR0=1;}//----------------------------------------------------------------------------------- //函数名:main();//函数功能:主函数入口;//------------------------------------------------------------------------------------ int main(){OUTPUT = 1;FREQ=10;TMOD=0X01;TR0=1;X1=(uint)(65536-(double)(500000/(1.020*FREQ)))/256; //定时器初值计算公式X2=(uint)(65536-(double)(500000/(1.020*FREQ)))%256;EX0=1;EX1=1;IT0=1;IT1=1;ET0=1;EA=1;LCD_init();string(0x80,"Have a nice day!");string(0xC0," Proteus VSM");delay(100);write_command(0x01);delay(100);while(1){delay(1000);write_command(0x80);string(0x80,"Frequency:");write_command(0x80+10);write_data(0x30+FREQ/1000);write_data(0x30+FREQ%1000/100);write_data(0x30+FREQ%1000%100/10);write_data(0x30+FREQ%1000%100%10/1); }}IO口开关实验main(){ucharkey_s,key_v;key_v = 0x03;LED = 0xfe;while(1){key_s = scan_key();if(key_s != key_v){delayms(10);key_s = scan_key();if(key_s != key_v){key_v = key_s;proc_key(key_v);}}}}ucharscan_key() {ucharkey_s;key_s = 0x00;key_s |= K2;key_s<<= 1;key_s |= K1;returnkey_s;}voidproc_key(ucharkey_v) {if((key_v& 0x01) == 0){LED = _cror_(LED,1);}else if((key_v& 0x02) == 0){LED = _crol_(LED, 1);}}LCD12864显示屏程序#define lcdrow 0xc0//设置起始行#define lcdpage 0xb8//设置起始页#define lcdcolumn 0x40//设置起始列#define c_page_max 0x08//页数最大值#define c_column_max 0x40//列数最大值//端口定义#define bus P0sbitrst=P2^0;sbit e=P2^2;sbitrw=P2^3;sbitrs=P2^4;sbit cs1=P2^5;sbit cs2=P2^6;//函数申明void delayms(uint); //延时n msvoid delayus10(void);//延时10usvoid select(uchar); //选择屏幕void send_cmd(uchar); //写命令void send_data(uchar); //写数据void clear_screen(void);//清屏void initial(void); //LCD初始化void display_zf(uchar,uchar,uchar,uchar); //显示字符void display_hz(uchar,uchar,uchar,uchar); //显示汉字void display(void); //在LCD上显示void main(){initial();display();clear_screen();display();while(1);}//延时10usvoid delayus10(void){uchar i=5;while(--i);}//延时10msvoid delayms(uint j){uchar i=250;for(;j>0;j--){ while(--i); i=249;while(--i);i=250;}}//屏幕选择-cs=0选择双屏,cs=1选择左半屏,cs=2选择右半屏void select(ucharcs){if(cs==0)cs1=1,cs2=1;else if(cs==1)cs1=1,cs2=0;else cs1=0,cs2=1;}//写命令void send_cmd(ucharcmd){rs=0;rw=0; bus=cmd;delayus10();e=1;e=0;}//写数据void send_data(uchardat){rs=1;rw=0; bus=dat;delayus10();e=1;e=0;}//清屏void clear_screen(void){ucharc_page,c_column;select(0);for(c_page=0;c_page<c_page_max;c_page++){send_cmd(c_page+lcdpage);send_cmd(lcdcolumn);for(c_column=0;c_column<c_column_max;c_column++) {send_data(0X00);}}}//LCD初始化void initial(void){select(0);rst=0;delayms(10);rst=1;clear_screen();send_cmd(lcdrow);send_cmd(lcdcolumn);send_cmd(lcdpage);send_cmd(0x3f);}//写字符//c_page为当前页,c_column为当前列,num为字符数,//offset为所取字符在显示缓冲区中的偏移单位voiddisplay_zf(ucharc_page,ucharc_column,ucharnum,uchar offset){uchar c1,c2,c3;for(c1=0;c1<num;c1++){for(c2=0;c2<2;c2++){for(c3=0;c3<8;c3++){send_cmd(lcdpage+c_page+c2);send_cmd(lcdcolumn+c_column+c1*8+c3);send_data(table_zf[(c1+offset)*16+c2*8+c3]);}}}}//写汉字//c_page为当前页,c_column为当前列,num为字符数,//offset为所取汉字在显示缓冲区中的偏移单位voiddisplay_hz(ucharc_page,ucharc_column,ucharnum,uchar offset){uchar c1,c2,c3;for(c1=0;c1<num;c1++){for(c2=0;c2<2;c2++){for(c3=0;c3<16;c3++){send_cmd(lcdpage+c_page+c2);send_cmd(lcdcolumn+c_column+c1*16+c3);send_data(table_hz[(c1+offset)*32+c2*16+c3]);}}}}//在LCD上显示void display(void) {select(1);display_zf(0,40,3,0); display_hz(2,0,4,0); display_hz(4,32,2,8); select(2);display_zf(0,0,4,3); display_hz(2,0,4,4); display_hz(4,0,2,10); }DHT11程序#include<reg52.h>#include<Time_Delay.h> sbit bit11=P2^0;unsignedcharU8T_data_H,U8T_data_L,U8RH_data_H,U8RH_data_L,U8check data;float F16T,F16RH; //用于最终读取的温湿度数据// read 8 bits onicechar COM(void){char i,U8temp,U8comdata;for(i=0;i<8;i++){while(!bit11);//表示读取的高电位延时大于20多us 则读取的是1 否则读取0Delay_us(35); //通过U8FLAG 可判断 bit11 显示数据的脉长U8temp=0;if(bit11)U8temp=1;while(bit11);U8comdata<<=1;U8comdata|=U8temp; //0}//rofreturn U8comdata;}//--------------------------------//-----温湿度读取子程序------------//--------------------------------//----以下变量均为全局变量--------//----温度高8位== U8T_data_H------//----温度低8位== U8T_data_L------//----湿度高8位== U8RH_data_H-----//----湿度低8位== U8RH_data_L-----//----校验8位== U8checkdata-----//----调用相关子程序如下----------//---- Delay();, Delay_10us();,COM();//--------------------------------void getDHT11(void){//主机拉低18msGO1: bit11=0;Delay_ms(20);bit11=1;//总线由上拉电阻拉高主机延时20usDelay_us(60);//主机设为输入判断从机响应信号// bit11=1;//判断从机是否有低电平响应信号如不响应则跳出,响应则向下运行if(!bit11) //T !{while(!bit11); //wait DHT goto highwhile(bit11);//数据接收状态U8RH_data_H=COM();U8RH_data_L=COM();U8T_data_H=COM();U8T_data_L=COM();U8checkdata=COM();bit11=1;//数据校验if((U8T_data_H+U8T_data_L+U8RH_data_H+U8RH_data_L)!=U8checkdata) //if check wrong,read againgoto GO1;}F16T=U8T_data_H+(float)U8T_data_L/256; //change integer to float F16RH=U8RH_data_H+(float)U8RH_data_L/256;}void Delay_ms(unsigned int n)//n毫秒延时{unsigned char j;while(n--){for(j=0;j<125;j++);}}void Delay_us(unsigned char n) //N us延时函数精度±4us{n=n/2;while(--n);}复位电路晶振电路。
基于Proteus的自动取款机设计与仿真作者:王赜坤来源:《现代电子技术》2013年第24期摘要:自动取款机系统采用高可靠性的AT89C52单片机作为核心控制芯片,采用具备I2C总线接口的FM24C02芯片完成密码与金额的存储,通过液晶显示器128×64显示运行状态和操作步骤。
软件设计采用具有较好移植性和可读性的C51语言编写程序,以便修改和增减功能。
通过Proteus软件成功实现了自动取款机的仿真过程。
经仿真表明,利用Proteus软件进行仿真设计可极大地简化单片机程序在目标硬件上的调试工作。
关键词: Proteus;自动取款机;液晶显示; AT89C52中图分类号: TN710.9⁃34 文献标识码: A 文章编号: 1004⁃373X(2013)24⁃0130⁃04 Design and simulation of ATM based on ProteusWANG Ze⁃kun(Huaxia College, Wuhan University of Technology, Wuhan 430223, China)Abstract: A high reliable microcontroller AT89C52 is used as the core control chip in the ATM system, in which FM24C02 chip with I2C bus interface is adopted to complete the storage of the cipher code and amount of money, and LCD128x64 is used to prompt the program’s running state and operating procedures. The system is convenient to modify or add/subtract function by using C51 language program, which is more transplantable and reliable. The simulation process of ATM was successfully realized by Proteus software. The simulation result shows that the SCM program debugging on the target hardware can be greatly simplified by using Proteus software.Keywords: Proteus; ATM; LCD; AT89C520 引言自动取款机,简称ATM(Automatic Teller Machine),它使用现代技术实现自动取款、修改密码、查询余额等操作,是业务电子化的一种机器设备,由于其便利性和实用性受到了人们的青睐。
基于P r o t e u s的A t m e g a48单片机P W M产生正弦波仿真(鹰击长空,l o n g s k y2007@126.c o m)1、仿真环境:u P r o t e u s P r o7.4s p3u I C C A V R6.31a2、电路原理图u外接4M晶振,熔丝位C L K D I V8无分频u外接R C复位电路u P W M经过两级低通滤波和放大电路u输出2.3V p p,1K H z正弦波3、程序u参照马潮《高档8位单片机A t m e g a128原理与开发应用指南(上)》P345/*版本:ICC A VR 6.25C,外接晶振4.00MHz,熔丝位CLKDIV8无分频*/#include <iom48v.h>#include <macros.h>/*const unsigned char auc_SinParam[128] = {128,134,140,147,153,159,165,171,177,182,188,193,199,204,209,213,218,222,226,230,234,237,240,243,245,248,250,251,253,254,254,255,255,255,254,254,253,251,250,248,245,243,240,237,234,230,226,222,218,213,209,204,199,193,188,182,177,171,165,159,153,147,140,134,128,122,116,109,103,97,91,85,79,74,68,63,57,52,47,43, 38,34,30,26,22,19,16,13,11,8,6,5,3,2,2,1, 1,1,2,2,3,5,6,8,11,13,16,19,22,26,30,34, 38,43,47,52,57,63,68,74,79,85,91,97,103,109,116,122}; // 128点正弦波样本值*/const unsigned char auc_SinParam[128] = {64,67,70,73,76,79,82,85,88,91,94,96,99,102,104,106,109,111,113,115,117,118,120,121,123,124,125,126,126,127,127,127,127,127,127,127,126,126,125,124,123,121,120,118,117,115,113,111,109,106,104,102,99,96,94,91,88,85,82,79,76,73,70,67,64,60,57,54,51,48, 45,42,39,36,33,31,28,25,23,21,18,16,14,12,10,9,7,6,4,3,2,1,1,0,0,0,0,0,0,0,1,1,2,3,4,6,7,9,10,12,14,16,18,21,23,25,28,31,33,36,39,42,45,48,51,54,57,60};// 马潮128点正弦波样本值unsigned char x_SW = 8,X_LUT = 0;// T/C0 溢出中断服务#pragma interrupt_handler Timer0_OVF_ISR:iv_TIMER0_OVF //17号中断void Timer0_OVF_ISR(void){//SEI();X_LUT += x_SW; // 新样点指针if (X_LUT > 127) X_LUT -= 128; // 样点指针调整OCR0A = auc_SinParam[X_LUT]; // 取样点指针到比较匹配寄存器// OCR0+=1;}void main(void){CLI();DDRD=0x40; // PD6输出方式:作为OC0A输出PWM波// Timer/Counter 0 initialization// Clock source: System Clock// Clock value: 4000.000 kHz// Mode: Fast PWM top=FFh// OC0 output: Non-Inverted PWMTCCR0B = 0x00;//stopTCNT0 = 0xFF;//setupTCCR0A=0x83;TCCR0B=0x01; //快速pwm 比较匹配发生时OC0A清零, 计数到TOP时OC0A置位.无预分频OCR0A=128;TIMSK0=0x01; // 允许T/C0溢出中断SEI();while(1);}。
前言学习单片机也有一段时间了,从模电、数电开始,一直到51、AVR回想起来真是一个漫长的过程啊。
我大学本是学的数学,开始就喜欢电脑这个东东,自然也就慢慢开始学习编程。
大学都被考试给耽误了,什么等级考试,程序员考试,从大二一直忙到大四,毕业了才发现自己除了比别人多了三四个证书外,别的就再没什么了。
编程除了学习谭老师的C和考二级时用TC 外,大二就开始接触VC了,但直到毕业也没把它玩转。
工作了,到公司才知道别人怎样用VC,后来在网上也认识了更多的高手,才发现自己的幼稚。
工作不到半年,就去了深圳,离开了内地,我才发现写程序要和单片机结合起来才更有前途,当然,也许我的认识到现在还是错误的。
因而回来之后我就找机会学习单片机,好在在大学考三级和高程时有一点硬件的理论,要不我想学起来就更难了。
也感谢现在网络资源丰富,我就BT了些资料,开是补充自己的硬件知识。
开始学习51时,朋友推荐了Protues,哇,第一次我就爱上她了,很快我找了些例子就把学到的理论给复习了一下;接下来我就进攻Atmega8了,因为我工作也用AVR的单片机,这样会方便些。
学习的过程是漫长的,但我并感觉不到辛苦,因为网上有那么多的朋友的例子,有那么多的资料供我去学习,还有我的女友的支持,我能感觉到的只是对知识的渴望。
为了更好的学习,我也买了块开发板,对学习的投资,我还是舍得的,呵呵。
但买回来发现,基本上那上面的功能,在Protues里都能实现,现在对ATmega8也基本了解了,我就想抽时间把自己学习的过程给整理一下,也给那些经济比较困难的学弟学妹们一点帮助。
同时也希望能有更多的朋友能奉献一点自己的热心,把自己的心得和经验贡献出来。
我希望自己总结的这份资料,可以在不用开发板的情况下去学习ATmega8,在您的电脑上装上Protues和icc Avr就可以了,我用的是Protues6.9和icc AVR6.3。
还没有回头整理,里面会有很多的错误,希望您发现了能发个email给我young45@。
arduino 用proteus仿真基础知识和实例Proteus 是一款功能强大的电子设计自动化软件,它可以帮助我们进行电路设计、仿真和制板。
在使用 Proteus 进行 Arduino 仿真时,需要了解一些基础知识和实例。
首先,需要在 Proteus 中创建一个新的项目,并选择适当的模板。
然后,可以在原理图编辑器中绘制电路原理图,添加 Arduino 芯片和其他元件。
在添加 Arduino 芯片时,需要选择正确的型号和引脚布局。
Proteus 提供了多种Arduino 芯片型号可供选择,例如 Uno、Nano、 Mega 等。
选择芯片后,可以将其放置在原理图上,并连接其他元件。
为了进行仿真,需要在 Proteus 中添加 Arduino 程序代码。
可以使用 Proteus 的 AVR 编译器来编译和上传代码到 Arduino 芯片中。
在编译和上传代码之前,需要设置正确的编译器路径和 Arduino 芯片型号。
一旦添加了代码,就可以开始进行仿真。
Proteus 提供了一个虚拟的 Arduino 芯片,可以模拟 Arduino 的行为。
可以通过观察虚拟芯片的输入和输出来验证电路的正确性。
以下是一个简单的 Proteus 仿真实例:1. 创建一个新的 Proteus 项目,并选择 AVR 模板。
2. 在原理图编辑器中绘制一个简单的电路,例如一个 LED 和一个电阻。
3. 添加 Arduino Uno 芯片,并将 LED 和电阻连接到相应的引脚。
4. 使用 Proteus 的 AVR 编译器编译并上传一个简单的 Arduino 程序,例如使 LED 闪烁。
5. 开始仿真,观察 LED 是否按照预期闪烁。
通过这个实例,可以了解如何使用 Proteus 进行简单的 Arduino 仿真。
需要注意的是,Proteus 仿真只是一种辅助工具,实际的 Arduino 硬件测试仍然是必要的。
Protel98电路仿真的基本步骤黄康才以基本放大器的时域(暂态)分析为例1、添加仿真元件库本例添加的仿真元件库路径在:\Client98\Sch\Library\Symbols.lib2、放置仿真元器件方法和绘制Sch原理图一样3、放置电源或信号源方法1:用菜单Simulate\Source下的命令方法2:用仿真电源工具条中的命令(执行菜单命令View\Toolbars\Simution Sources命令来切换) 。
本例用+12V的电源和10K、1mV的正弦信号。
4、设置节点方法1、用Place\Net Label命令;方法2、用画线工具条中的Net命令(执行菜单命令View\Toolbars\Wrings Tools命令来切换)。
最好,电路如下:5、启动仿真本例进行时域(暂态)模拟,所以执行Simulate\Setup Simulator\Transient 命令,即6、进行仿真设置。
在上一步骤中弹出“时域分析对话框”:其中:Duration(s):指时域分析结果显示的时间长度。
一般显示信号三、四个周期的波形比较合适。
Display(s):指相邻显示点的时间间隔。
Start(s):显示起始时间,缺省为0。
Run:单击该按钮,程序开始进行时域分析。
最后得到仿真结果:如何设置直流仿真激励源黄康才引言:Protel98可在原理图的基础上进行模拟。
模拟前要在进行模拟的原理图上放置激励源。
直流仿真电源用于产生直流电压和电流。
包括VSRC(直流电压)仿真电源和ISRC(直流电流)(如图1所示)。
图1如图3中,模拟激励源工具栏提供了四种电压的直流源,它们分别是+12V、 -12V、+5V和-5V四种,这四种是最常用到的直流激励源。
如果你所放置的直流源的幅度与这些不同,可在属性对话框中修改。
例题:在原理图上放置一个名称为VCC的+5V直流源。
重点:属性的设置。
过程:1、新建一个SCH文件。
2、在新建的原理图上放置一个+5V的直流源。
atmega8 模拟比较中断函数ATmega8是一款8位微控制器,它具有模拟比较器,可以用于检测模拟信号的大小关系。
当模拟信号满足特定条件时,可以触发中断函数。
以下是ATmega8模拟比较中断函数的详细说明:1. 中断函数的定义ATmega8中断函数需要使用ISR宏定义来定义。
例如,当比较器输出引脚(ACO)变化时触发中断,可以使用以下代码定义中断函数:ISR(ANALOG_COMP_vect){// 中断处理代码}其中,ANALOG_COMP_vect是ATmega8内置模拟比较器中断向量的名称。
2. 中断使能在使用ATmega8模拟比较器中断之前,需要先使能该中断。
可以通过设置ACSR寄存器来实现。
例如,以下代码将启用模拟比较器中断:ACSR |= (1 << ACIE);其中,ACIE位用于启用模拟比较器中断。
3. 中断触发条件ATmega8模拟比较器有两个输入端口:正端口和负端口。
当正端口电压高于负端口电压时,比较器输出引脚(ACO)为高电平;反之则为低电平。
因此,在使用模拟比较器中断之前需要确定触发条件。
例如,如果希望当正端口电压高于负端口电压时触发中断,可以使用以下代码设置比较器正端口输入(AIN0)和参考电压(AREF)作为负端口输入:ADMUX |= (1 << MUX0); // 设置AIN0为正端口输入ACSR |= (1 << ACBG); // 设置AREF为负端口输入4. 中断处理当模拟比较器输出引脚(ACO)变化时,触发中断函数。
在中断函数中可以编写相应的处理代码。
例如,以下代码将在比较器输出引脚变为高电平时打开LED灯:ISR(ANALOG_COMP_vect){PORTB |= (1 << PB0); // 打开LED灯}5. 中断清除当中断函数执行完毕后,需要清除中断标志位以允许下一次中断触发。
可以通过读取ACSR寄存器的ACI位来清除模拟比较器中断标志位。
前言学习单片机也有一段时间了,从模电、数电开始,一直到51、AVR回想起来真是一个漫长的过程啊。
我大学本是学的数学,开始就喜欢电脑这个东东,自然也就慢慢开始学习编程。
大学都被考试给耽误了,什么等级考试,程序员考试,从大二一直忙到大四,毕业了才发现自己除了比别人多了三四个证书外,别的就再没什么了。
编程除了学习谭老师的C和考二级时用TC 外,大二就开始接触VC了,但直到毕业也没把它玩转。
工作了,到公司才知道别人怎样用VC,后来在网上也认识了更多的高手,才发现自己的幼稚。
工作不到半年,就去了深圳,离开了内地,我才发现写程序要和单片机结合起来才更有前途,当然,也许我的认识到现在还是错误的。
因而回来之后我就找机会学习单片机,好在在大学考三级和高程时有一点硬件的理论,要不我想学起来就更难了。
也感谢现在网络资源丰富,我就BT了些资料,开是补充自己的硬件知识。
开始学习51时,朋友推荐了Protues,哇,第一次我就爱上她了,很快我找了些例子就把学到的理论给复习了一下;接下来我就进攻Atmega8了,因为我工作也用AVR的单片机,这样会方便些。
学习的过程是漫长的,但我并感觉不到辛苦,因为网上有那么多的朋友的例子,有那么多的资料供我去学习,还有我的女友的支持,我能感觉到的只是对知识的渴望。
为了更好的学习,我也买了块开发板,对学习的投资,我还是舍得的,呵呵。
但买回来发现,基本上那上面的功能,在Protues里都能实现,现在对ATmega8也基本了解了,我就想抽时间把自己学习的过程给整理一下,也给那些经济比较困难的学弟学妹们一点帮助。
同时也希望能有更多的朋友能奉献一点自己的热心,把自己的心得和经验贡献出来。
我希望自己总结的这份资料,可以在不用开发板的情况下去学习ATmega8,在您的电脑上装上Protues和icc Avr就可以了,我用的是Protues6.9和icc AVR6.3。
还没有回头整理,里面会有很多的错误,希望您发现了能发个email给我young45@。
您有什么要补充的或自己的心得也可以写信过来,我和以后学习这份资料的人谢谢您的奉献。
另外我没有提供源码,是为了触发您自己动手做,不要找到源码放到环境中运行一下就OK了,那样你的印象不深刻。
另外,看本资料之前,希望你先了解一下ATmega8的硬件环境,我推荐您看清华大学的《ATmega8原理及应用》;最好你也有一定的C语言基础。
最后,很感谢这段女友对我的照顾,我是个懒惰的人,是她促使我把自己的协作完成的。
老杨2006年11月于古都洛阳young45@第二讲 LED数码管的学习提要:主要学习Atmega8通用数字I/O接口控制LED数码管的应用。
2.1 I/O口的结构及特点:Atmega8有23个I/O引脚,分成3个8位的端口B、C和D,其中C口只有7位。
I/O端口作为通用数字输入/输出口使用时,都具备真正的读-修改-写(R-M-W)特性。
每个I/O引脚采用推挽式驱动,不仅能提供大电流的输出驱动,而且也可以吸收20mA的电流,因而能直接驱动LED显示器。
Atmega8采用3个8位寄存器来控制I/O端口,它们分别是方向寄存器DDRx,数据寄存器PORTx 和输入引脚寄存器PINx(x为B或C或D,分别代表B口、C口或D口;n为0~7,代表寄存器中的位置),其中DDRx和PORTx是可读写寄存器,而PINx 为只读寄存器。
每个I/O引脚内部都有独立的上拉电阻电路,可通过程序设置内部上拉电阻是否有效。
方向寄存器DDRx中的每个位用于控制I/O口一个引脚的输入输出方向,即控制I/O口的工作模式为输出模式还是输入模式。
当DDRxn=1时,I/O的Pxn引脚处于输出模式。
此时当PORTxn=1时,I/O 引脚呈高电平,同时可提供输出20mA的电流;当PORTxn=0时,I/O引脚呈低电平,同时可吸收20mA的电流。
当DDRxn=0时,I/O的Pxn引脚处于输入模式。
此时引脚寄存器PINxn中的数据就是外部引脚的实际电平。
此时可通过PORTxn的设置可控制内部的上拉电阻使用或不使用。
表2-1 I/O口设置表(n=7,6,…,1,0)DDRxn PORTxn PUD I/O模式内部上拉电阻引脚状态说明0 0 X 输入无效三态(高阻)0 1 0 输入有效外部引脚拉低时输出电流0 1 1 输入无效三态(高阻)1 0 X 输出无效低电平推挽输出,吸收电流(≤20mA)1 1 X 输出无效高电平推挽输出,输出电流(≤20mA)通用I/O口主要特点:1 都具备真正的读-修改-写(R-M-W)。
2 双向,可独立位控制。
3 大电流驱动(≤20mA),可直接驱动LED。
4 可控制上拉电阻。
注意事项:1 使用AVR的I/O口,首先应正确设置其工作模式(输入模式还是输出模式),设置DDRx。
2 当I/O工作在输入模式(DDRxn=0)时,读取引脚上的电平应取PINxn的值,而不是PORTxn的值。
3 当I/O口工作在输入模式(DDRxn=0)时,应根据实际情况设置内部上拉电阻,利用内部上拉电阻可以节省外部上拉电阻。
4 将I/O空工作模式由输出模式设置为输入模式后,必须等待一个时钟周期后才能正确的读到外部引脚的值。
2.2 跑马灯程序控制发光二极管回顾了这么久的理论,下面我们也做一个例子,功能是用PD口控制8个发光二极管循环点亮,形成“跑马灯”。
试着在Proteus中画出电路图,看是否和我的一样呢,不一样也不怕,也许你比我画的更好呢?在ICC中编写C程序,先把你的想法写出来,编译在Proteus跑一下,看你的“跑马灯”是否真的跑起来了,下面是我的参考程序:怎么样,你的灯亮了吗,很兴奋吧,很有成就感吧。
现在你已经开始了解AVR单片机了,同时还掌握了两个软件的使用。
想一想:如果改变delay_ms的时间会变的怎样呢;如果直接让PORTD=(1<<i)呢;能不能添加或修改程序,改变灯亮的顺序和时间呢?我相信你都能完成的。
2.3 单个LED数码管练习好了,接下来我们进一步学习LED数码管的控制,在进行新的实验之前,我们先了解一下LED数码管。
其实LED数码管的应用就在我们周围,在电梯上和小家电上我们经常会看到它,LED数码管显示器内部由七个条形发光二极管和一个小圆点发光二极管组成,每个发光二极管称为一字段。
因而它的控制原理和发光二极管的控制原理是相同的。
根据各管的接线形式,可分成共阴极型和共阳极型。
给LED数码管的七个发光二极管加不同的电平,二极管显示不同亮暗的组合就可以形成不同的字形,这种组合称之为字形码。
下面以1为高电平,0为低电平,给出字形码表。
显示字型h g f e d c b a 共阴极字形码共阳极字形码0 0 0 1 1 1 1 1 1 0x3F 0xC01 0 0 0 0 0 1 1 0 0x06 0xF92 0 1 0 1 1 0 1 1 0x5B 0xA43 0 1 0 0 1 1 1 1 0x4F 0xB04 0 1 1 0 0 1 1 0 0x66 0x995 0 1 1 0 1 1 0 1 0x6D 0x926 0 1 1 1 1 1 0 1 0x7D 0x827 0 0 0 0 0 1 1 1 0x07 0xF88 0 1 1 1 1 1 1 1 0x7F 0x809 0 1 1 0 1 1 1 1 0x6F 0x90A 0 1 1 1 0 1 1 1 0x77 0x88b 0 1 1 1 1 1 0 0 0x7C 0x83C 0 0 1 1 1 0 0 1 0x39 0xC6d 0 1 0 1 1 1 1 0 0x5E 0xA1E 0 1 1 1 1 0 0 1 0x79 0x86F 0 1 1 1 0 0 0 1 0x71 0x8E有了字形码表,我们就可以编程了。
如果还用PD口来控制一个LED数码管的八个字段,那么当要显示0~F的一个字型时,我们给PD口输出对应的字形码就可以了。
如要在共阴极的数码管显示6,则PD口输出0x7D就可以了;要显示9则PD口输出0x6F。
下面我们就做一个用LED数码管显示数字0~9的例子,我们还用PD口控制,循环显示,间隔500MS显示一个数字。
好想想我们怎么用Proteus画出电路呢,我们的程序又该怎么设计呢。
下面我给出自己的参考电路:也给出我的C语言主程序的参考,延时函数还是用上面的,这个延时不是很准确,要用精确的延时我们后面会学到定时器,这里我们就先用软件延时。
怎么样你的数字也显示出来了吗,我想一定显示的很好吧。
那么要是我想显示A~F怎么办呢;能不能显示象H,L一类的字母呢;改变了delay_ms函数的延时时间会怎样呢;要显示小数点我们应该怎么办呢?我想你都能帮我找出答案吧,那还不快点去试试。
2.4 多个LED数码管实验学会用一个LED数码管显示数字了,一定很高兴吧,接下来我们就要试用多个数码管显示数字了,我想你住的楼房的层数也快超过10的限制了吧。
首先我来介绍一下多个数码管的显示:多位LED数码管显示电路按驱动方式分可分为静态显示和动态显示两种方法。
所谓静态显示就是除了要改变显示数据,所有的数码管都处于加电状态,上面的例子就是静态显示。
它的优点是:显示稳定,亮度高,程序设计简单,MCU 负担小。
缺点就是占用资源多,耗电量大,若用静态显示方式,一个Atmega8也就可以负载3个LED数码管,因此我们常考虑采用动态显示的方法。
动态显示就是采用各数码管循环轮流显示的方法,当循环显示频率教高时,利用人眼的暂留特性,感觉不到数码管的闪烁,就像看到数码管在同时发光一样,类似电影的原理。
这种显示需要一个接口完成字形码的输出,另外一个接口完成各数码管的轮流显示。
其优点是:占用资源少,耗电量小;缺点是:显示稳定性不易控制,程序设计复杂,MCU负担重。
下面我们就试着用多个数码管做个计数器,用PB口做字形码的输出口,用PC0~PC3控制数码管的轮流显示。
先是显示“000.0”四个数字,四秒钟后开始计数,由十分位开始,到十进位,最大为“999.9”最后变回初始状态。
给你五分钟时间考虑一下程序怎么设计。
怎么样想好了吗,现在电路的设计已经不是问题了吧,我想你心里已经把它画好了吧。
好我这里给出一个参考:我写的主程序是这样的(延时函数还借用前面的),可以实现,但一定不是最好的,我想你一定能设计出比我写的更好的程序吧:很好,现在你已经对Atmega8的通用I/O口很熟悉了,而且对Proteus也很熟悉了吧,怎么样对LED数码管已经感觉熟烂于胸了吧。
非常高兴看到你的进步!!好了,到目前为止,我们对LED数码管的学习就可以告一段落了;但是我们还有一些新的事物还没看到,需要我们更加努力的去学习、实践在以后的工作中学习更多的知识。