AVR学习笔记
- 格式:doc
- 大小:255.00 KB
- 文档页数:12
AVR学习笔记前言:学习一块单片机,我们要几项准备工作:1.开发软件(熟悉开发软件操作流程,基本上开发软件都差不多的,学会了一款,再学其它的就会很顺手了(新建工程、新建设计文件、把源文件加到工程里面、最后设置一些参数)2.编程语言(这个就不用说了,先学语法规则,能够熟练掌握到自己写的代码没有语法错误,然后再逐步把自己的想法驾驭到编程语言上)3.硬件(硬件包括的范围很广,不仅包括你所要学的单片机还有单片机的外围电路所用到的器件),最好要学一款仿真软件。
我们始终要记住学单片机绝对不可以纸上谈兵,一定要实践,就是把自己所写的代码下载到板上,看看实际效果。
开发板可以买,也可以自己做!我喜欢自己做。
实验一:点亮发光二极管1.avr单片机的i/o端口1)学习单片机的主要任务就是了解、掌握单片机i/o端口的功能,以及如何正确设计这些端口与外围电路的连接,从而能够组成一个嵌入式系统,并编程、管理和运用他们完成各种各样的任务。
2)atmega16有4个8位的双向i/o端口pa、pb、pc、pd,他们对外对应32个i/o引脚,每一位都可以独立地用于逻辑信号的输入和输出。
在5v工作电压下,输出高点平时,每个引脚可输出达20ma的驱动电流;而输出低电平时,每个引脚可吸收最大为40ma的电流,可以直接驱动发光二极管(一般的发光二极管的驱动电流为10ma)和小型继电器等小功率器件。
avr大部分的i/o端口都具备双重功能(有的还有第三功能)。
其中第一功能是作为数字通用i/o接口使用,而复用的功能可分别与片内的各种不同功能的外围接口电路组合成一些可以完成特殊功能的i/o口,如定时器、计数器、串行接口、模拟比较器、捕捉器、usart、spi等。
3)avr单片机的每组i/o口都搭载存有三个8为寄存器,分别就是:方向掌控寄存器ddrx、数据寄存器portx、输出插槽寄存器pinx(x=a/b/c/d).i/o口的工作方式和整体表现特征由这三个i/o寄存器掌控。
IAR for AVR 学习笔记IAR FOR AVR 学习笔记在AVR编程一直是C,从ICC->GCC->IAR IAR是一个唯一自己选择的.ICC由于入门容易所以选择了开始,GCC因为不要钱,所以后来就用了它.随着对GCC的不断认识,缺点不断显露,开始对IAR产生了兴趣.IAR在51,AVR,ARM的C上都是非常优秀的,它针对不同的单片机都有不同的C版本.唯一一点遗憾的是IAR的价格是个人和小公司难以承受的.当然网上有很多破解,现在的最新版4.20A也有了破解.IAR FOR AVR相关信息:破解方法:ID号注意一定要大写,不然注册将会失败 ,另外并不是每个号都是能用的了,要多试几次.如果注册成功后,编译就会通过.不然就报\没有可的证书\错误. 注意点:如何输出HEX文件?在配置文件后面加入以下代码,便可输出HEX文件,A90文件与HEX文件一样,SLISP都能识别.// Output File-Ointel-extended,(XDATA)=.eep //产生eeprom文件 -Ointel-extended,(CODE)=.A90 //产生烧写文件 -Ointel-extended,(CODE)=.hex //产生烧写文件中断向量的使用IAR中定义中断函数的格式是 ///////////////////////////////// #pragma vector=中断向量__interrupt void 中断服务程序(void) {//中断处理程序 }/////////////////////////////////////中断的初始化要另外加入代码,可在主程序内加入。
如下是各个中断函数的定义。
//中断定义#include#pragma vector=INT0_vect__interrupt void INT0_Server(void) { }#pragma vector=INT1_vect__interrupt void INT1_Server(void) { }#pragma vector=TIMER2_COMP_vect__interrupt void TIMER2_COMP_Server(void) { } #pragma vector=TIMER2_OVF_vect__interrupt void TIMER2_OVF_Server(void) { } #pragma vector=TIMER1_CAPT_vect__interrupt void TIMER1_CAPT_Server(void) { } #pragma vector=TIMER1_COMPA_vect__interrupt void TIMER1_COMPA_Server(void) { } #pragma vector=TIMER1_COMPB_vect__interrupt void TIMER1_COMPB_Server(void) { } #pragma vector=TIMER1_OVF_vect__interrupt void TIMER1_OVF_Server(void) { } #pragma vector=TIMER0_OVF_vect__interrupt void TIMER0_OVF_Server(void) { } #pragma vector=SPI_STC_vect__interrupt void SPI_STC_Server(void) { }#pragma vector=USART_RXC_vect__interrupt void USART_RXC_Server(void) { } #pragma vector=USART_UDRE_vect__interrupt void USART_UDRE_Server(void) { } #pragma vector=USART_TXC_vect__interrupt void USART_TXC_Server(void) { } #pragma vector=ADC_vect__interrupt void ADC_Server(void) { }#pragma vector=EE_RDY_vect__interrupt void EE_RDY_Server(void) { }#pragma vector=ANA_COMP_vect__interrupt void ANA_COMP_Server(void) { }#pragma vector=TWI_vect__interrupt void TWI_Server(void) { }#pragma vector=INT2_vect__interrupt void INT2_Server(void) { }#pragma vector=TIMER0_COMP_vect__interrupt void TIMER0_COMP_Server(void) { }#pragma vector=SPM_RDY_vect__interrupt void SPM_RDY_Server(void) { }如何把常数字符串定义在flash 空间?法一:unsigned char __flash temptab[] = {1,2,3,4,5}; 法二:__flashunsigned char temptab[] = {1,2,3,4,5}; 法三:#pragma type_attribute=__flash unsigned char temptab[]={1,2,3,4,5};法四:const unsigned char temptab[]={1,2,3,4,5};注:第三种方式用#pragma说明后,下面的定义的变量将都在FLASH空间了,用于定义一批FLASH变量,但实际上一般只能作为常量使用了.感谢您的阅读,祝您生活愉快。
1.输入状态IO寄存器设置DDRx某一位置0,相应位的IO口被设置为输入输出|=(置1),输入&=~(置0)PORTx某一位置1,使能对应IO口相应位的上拉电阻PINx的对应位是输入的数据,0或1头文件是includ <avr/io.h>2.ISC2为0时,外部中断2是下降沿触发,为1时,是上升沿触发。
3. 4.1.2.T/C寄存器在全局变量前加volatile,这个变量才能应用在中断程序中USART 1.2.GCC编程1)另外,宏_BV(bit) 是我们操作I/O 寄存器时频繁用到的,avr-libc 建议使用这一宏进行寄存器的位操作,它在文件sfr_defs.h 中定义如下:#define _BV(bit) (1 << (bit))2)avr-libc 建议使用一组数据类型符号,这些数据类型的定义在头文件inttype.h 中,头文件的包含形式如下:#include <inttype.h>其中定义了常用的整数类型如下表所示3)const int n = 5;4)int a[n];注意:在ANSI C中,这种写法是错误的,因为数组的大小应该是个常量,而const int n,n只是一个变量(常量!= 不可变的变量,但在标准C++中,这样定义的是一个常量,这种写法是对的),实际上,根据编译过程及内存分配来看,这种用法本来就应该是合理的,只是ANSI C对数组的规定限制了它。
5)那么,在ANSI C 语言中用什么来定义常量呢?答案是enum类型和#define宏,这两个都可以用来定义常量。
6)在程序中访问 FLASH 程序存储器avr-libc 对FLASH 存储器的读写支持API 和宏在头文件pgmspace.h中定义,在源文件中的包含形式如下:#include < avr/pgmspace.h >在程序存储器内的数据定义使用关键字__attribute__((__progmem__))。
PC = progammer counter //程序计数器ACC = accumulate //累加器PSW = progammer status word //程序状态字SP = stack point //堆栈指针DPTR = data point register //数据指针寄存器IP = interrupt priority //中断优先级IE = interrupt enable // 中断使能TMOD = timer mode //定时器方式 (定时器/计数器控制寄存器)ALE = alter (变更,可能是)PSEN = progammer saving enable //程序存储器使能(选择外部程序存储器的意思) EA = enable all(允许所有中断)完整应该是 enable all interruptPROG = progamme (程序)SFR = special funtion register //特殊功能寄存器TCON = timer control //定时器控制PCON = power control //电源控制MSB = most significant bit//最高有效位LSB = last significant bit//最低有效位CY = carry //进位(标志)AC = assistant carry //辅助进位OV = overflow //溢出ORG = originally //起始来源DB = define byte //字节定义EQU = equal //等于DW = define word //字定义E = enable //使能OE = output enable //输出使能RD = read //读WR = write //写中断部分:INT0 = interrupt 0 //中断0INT1 = interrupt 1//中断1T0 = timer 0 //定时器0T1 = timer 1 //定时器1TF1 = timer1 flag //定时器1 标志 (其实是定时器1中断标志位)IE1 = interrupt exterior //(外部中断请求,可能是)IT1 = interrupt touch //(外部中断触发方式,可能是)ES = enable serial //串行使能ET = enable timer //定时器使能EX = enable exterior //外部使能(中断)PX = priority exterior //外部中断优先级PT = priority timer //定时器优先级PS = priority serial //串口优先级第一部分二极管发光的条件是正负极相差达1V以上。
一、AVR的PC口正常使用:1、在程序中连续写入两条语句:MCUCSR |= BIT(7);( 或者是MCUCSR =(1<<7); )。
2、将熔丝位OCDEN 和JTAGEN 设置为0,关闭仿真功能。
编译时出现错误警告:!E <library>(72): area 'data' not large enough解决方法:project----compiler----勾上Treat"const"as"_flash"解释:将定义的const较大数组装入flash.二、如何通过AVR_fighter对EEPROM编程:在运用ICCAVR编程时对需要写入EEPROM的数据作如下处理:///////////////////////////////////////////////////////#pragma data:eepromunsigned char table[]={0x01,0x02} //定义要写入EEROM的数据#pragma data:data并将#include <eeprom.h> 加入C代码中。
////////////////////////////////////////////////////////通过以上处理后的数据在编译时会被ICCAVR编译生成*.eep文件,将此文件加入AVR_fighter的装EEPROM ,AVR_fighter在编程flash时相应会编程EEPROM。
三、将SPI初始化为主机,进行简单的数据发送。
例子中SSR_SIP必须由实际的数据方向寄存器代替。
void spi_maxterinit (void){DDR_SPI = (I<<DD_MOSI)|(1<<DD_SCK); //设置MOSI和SCK为输出,其他为输入SPCR = (1<<SPE)|(1<<SPR0); //使能SPI主机模式,设置时钟速率为fck/16}void SPI_MasterTransimt(char cData){SPDR = cData; //启动数据传输while(!(SPRS & (1<<SPIF))); //等待传输结束}///////////////////////////////////////////////////////////////////////////////////////////////////////////例子假定已经饱含了正确的头文件:Void SIP_SlaveInit(void){DDR_SPI = (1<<DD_MISO); //设置MISO为输出,其他为输入SPCR = (1<<SPE); //使能SPI}Char SPI_SlaveReceive(void){While (!( SPSR & (1<<SPIF ))){};Return SPDR;}四、对一个十六进制数的某一位取反Num = num^( 1<< wei );五、STC自动下载:Include <reg52.h>Sfr ISP_CONTR =0XE7;sbit ISP=P3^0;void main(void){TMOD |= 0X01;TH0=0X00;TL0=0X00;EA=1;ET0=1;TR0 =1;}void Timer0_isr(void) interrupt 1 using 1{TH0=0x00; //重新赋值TL0=0x00;while(ISP==0){ISP_CONTR=0XE0;}}。
AVR学习笔记六、模拟比较器和ADC实验-------基于LT_Mini_M166.1 模拟比较器实验6.1.1实例功能模拟比较器和模数转换ADC是单片机内部最常见的两种支持模拟信号输入的功能接口。
大部分AVR都具备这两种类型的接口。
本实例将以ATmage16芯片为例,介绍模拟比较器的使用方法,在下一个实例中介绍模数转换ADC。
使用模拟比较器可以实现单片机系统电源电压的检测,更巧妙的应用是利用模拟比较器和一些简单的外围电路,设计简单的模数转换ADC。
本实例实现利用模拟比较器比较某一点电压与内部模拟比较器参考电压的高低。
共有3个功能模块,分别描述如下:●单片机系统:使用ATmega16单片机的模拟比较器比较某一点的电压与参考电压的关系。
●外围电路:利用电阻设计的分压电路。
●软件程序:熟悉掌握ATmega16单片机的模拟比较器的使用。
通过本实例的学习,掌握相关电路设计,并掌握以下知识点:●了解单片机的模拟比较器。
●了解单片机的模拟比较器的使用。
●掌握单片机模拟比较器的编程。
6.1.2、器件和原理1、模拟比较器的介绍ATmega16的模拟比较器可以实现对两个输入端:正极AIN0和负极AIN1(分别对应于ATmage16的引脚PB2、PB3)的模拟输入电压进行比较。
当AIN0上的电压高于AIN1的电压时,模拟比较器输出ACO被设为“1”。
比较器的输出还可以被设置作为定时计数器1输入捕获功能的触发信号。
此外,比较器的输出可以触发一个独立的模拟比较器中断。
用户可以选择使用比较器输出的上升沿、下降沿或事件触发作为模拟比较器中断的触发信号。
2、与模拟比较器相关的寄存器与模拟比较器相关的寄存器是SFIOR、ACSR。
用户通过这两个寄存器的相关位实现对模拟比较器的设置和控制。
1)特殊功能IO寄存器—SFIOR时模数转换(ADC)功能被关闭(ADCSRA寄存器中的ADEN使能位为“0”)时,允许使用ADC 多路复用器选择ADC的模拟输入端口作为模拟比较器反向端的输入信号源。
A VR学习笔记之【外部中断】【一】Mega16共有三个外部中断,外部中断相比定时器而言它的寄存器比较少,因此相对比较简单。
我们现在只关心需要用的部分,其他的暂且放弃不管。
和外部中断相关的特殊功能寄存器有:①MCU控制寄存器(MCUCR)在上面八位的寄存器中,白色的部分使我们要关心的,灰色部分就不用管了。
资料上对后面四位(第四位)的作用有介绍。
ISC11与ISC10控制中断1的触发方式。
下表为ISC10/11的值对应触发方式:SC11与ISC10控制中断0的触发方式。
下表为ISC00/01的值对应触发方式:我们在使用外部中断0和1的时候,其触发方式的设置便是通过以上ISC的不同值实现的。
至于INT2下面有介绍。
②MCU控制与状态寄存器(MCUCSR)这个寄存器只有一个BIT与外部中断相关。
ISC2,我们通过和INT0/1的对比可以发现ISC的后缀数字命名只有规律的,这会方便我们记忆。
同时在说明文档上说了很长一段关于ISC2的说明:他的意思说早了,他也就是想说:ISC=0的话INT2是下降沿出发中断,ISC=1是上升沿出发。
这才是应该说明的最重要的点。
他后面还说了:(1)如果你让ISC=0那么外部的低电平必须保持到当前正在运行的指令运行结束才会出发,换一句意思就是,如果外部时间过短,有可能导致INT2不被触发。
(2)他又说明,如果改变ISC2的值的话有可能触发中断,导致误判,因此如果你想改变其中断触发方式的话,首先把通用中断控制寄存器(GICR)里面控制INT2的中断开关关了,这样便不会触发中断了。
③通用中断控制寄存器(GICR)他就是个中断开关。
前面三位依次赋值便会打开响应中断。
当然总中断开关也要打开才行(SREG|=BIT(7))。
④通用中断标志寄存器(GIFR)他就是一个中断标志,我们也就是说在中断发生的时候中断对用的标志会变为1,此时程序会自动转到中断程序子函数。
然后有硬件自动清零,以等待下一次的中断发生。
A VR学习笔记二、基本输入和外部中断实验-------基于LT_Mini_M162.1 利用按键控制发光二极管的亮灭2.1.1 实例功能在“点亮发光二极管”和“让发光二极管动起来”这两个例子中,都是通过单片机程序来控制发光二极管的亮灭。
如果想要控制发光二极管的亮灭,只有通过打开或者关闭电源来实现控制。
那么怎样实现人工参与控制呢?在有些应用场合,需要单片机对人工的开关信号作出相应的响应和处理,通过控制电源的通断会影响到单片机系统中的其他功能,所以通过控制电源的方法并不明智。
能不能通过按动一个按键来实现发光二极管的亮灭呢?当然可以,前面已经讲过,A VR单片机的I/O口都是双向的,也就是既能当作输出控制端口,也能当作输入检测端口。
既然我们可以通过控制端口输出不同的高低电平使发光二极管实现点亮和熄灭;那么为什么不能通过监测端口输入电平的状态来进行相应的处理呢。
在本例中,通过介绍利用按键开关控制发光二极管的亮灭来了解A VR单片机的端口检测外部信号的功能和方法。
本例中有3个功能模块,描述如下:●单片机系统:检测外界的按键开关信号,根据按键的开关状态控制发光二极管的亮灭状态。
●外围电路:首先是产生信号的按键电路,包括对按键去抖动电路的介绍;然后是发光二极管的控制电路。
●软件程序:通过读取AVR单片机相应端口的状态,编写相应的程序控制发光二极管的亮灭。
本例的目的在于希望读者完成本例后,能完成相关电路的设计和相应程序的编写,从而掌握以下知识点:◆了解AVR单片机端口输入功能,掌握使用AVR单片机端口输入功能检测外部信号的原理。
◆熟悉单片机端口输入输出功能的综合使用。
◆掌握AVR单片机按键的硬件去抖动的电路设计和原理。
◆掌握AVR单片机端口输入输出程序的编写。
◆掌握AVR单片机按键软件去抖动功能的实现。
2.1.2 器件和原理本例主要介绍A VR单片机外围电路中按键去抖电路的设计,分别介绍相应的软件和硬件解决方案。
林夕依然ATmega16学习笔记例程移植到Atmel Studio 6.2笔记相信你已经有了一定的C语言及数字电路基础,以及能定下心来,决心学点东西。
如果做不到的话,麻烦您把我轻轻的放开,该干啥干啥去。
前言最近学习A VR,网上找了N多资料后,发现就算林夕依然ATmega16学习笔记最合俺的心意。
优点如下:1、不讲原理,直接操作,适合俺这种不愿背书的差生。
2、每个例程都附有源程序及PROTEUS仿真文件,省了买零件的金钱及焊板的时间。
缺点当然也有:1、太省事了,初学者容易只跑跑例程,不求甚解(这也是市售所有学习板的通病)。
2、基于ICCA VR,而不是最新的AtmelStudio。
3、理论知识太少(也算是优点)。
还有一条就是这玩意是用EXE文件打包的,初次下载时,我不敢打开,生怕会给我强装软件或者开个后门什么的。
后来在网上下载了一个开发板的附带光盘文件,发现里面也带着这玩意。
心想这里面不该会有问题呀,才不是太放心的打开,打开后发现相见恨晚呀!好吧,先把这些例程一个一个琢磨完吧。
不过看程序时发现想打瞌睡,也难怪,看这玩意也太没挑战性了。
既然我的电脑中装了AtmelStudio,即然ICCA VR迟早要过时,不如把这里面的例程移植到AtmelStudio中吧!顺便也可以学习一下编程。
笔记不妨公开,俺也好刷一点成在感。
本文中所有例程均在AtmelStudio6.2+Proteus7.8中调试通过。
本文是我个人学习时的笔记,希望后来者能少走一点弯路。
学习MCU的惟一捷径是多读例程,多写程序,别无他法。
林夕依然ATmega16学习笔记下载链结如下:链接:密码:mzah实验1:8种LED点亮模式1、移植到AtmelStudio中的步骤打开Atmel Studio 6.2,新建一个项目。
不知道啥意思,我选第二个后,在下面起好项目名称及选好项目目录后OK。
这个好办,按CPU型号选就好了。
终于进入编辑窗口了。
一言蔽之,提取包中所有.c(C源码)、.h(C头文件)、.dsn(PROTEUS仿真文件)文件。
MCU控制寄存器—MCUCRBit 1 – IVSEL: 中断向量选择IVSEL为"0―时,中断向量位于Flash存储器的起始地址;IVSEL 为"1―时,中断向量转移到Boot 区的起始地址。
实际的Boot 区起始地址由熔丝位BOOTSZ 确定。
为了防止无意识地改变中断向量表,修改IVSEL 时需要遵循如下过程:1. 置位中断向量修改使能位IVCE2. 在紧接的4 个时钟周期里将需要的数据写入IVSEL,同时对IVCE 写‖0‖执行上述序列时中断自动被禁止。
其实,在置位IVCE 时中断就被禁止了,并一直保持到写IVSEL 操作之后的下一条语句。
如果没有IVSEL 写操作,则中断在置位IVCE 之后的4个时钟周期保持禁止。
需要注意的是,虽然中断被自动禁止,但状态寄存器的位I并不会因此而受到影响。
Note: 若中断向量位于Boot Loader区,且Boot锁定位BLB02被编程,则执行应用区的程序时中断被禁止;若中断向量位于应用区,且Boot锁定位BLB12 被编程,则执行Boot Loader区的程序时中断被禁止。
有关Boot锁定位的细节请参见P241‖Boot Loader 支持RWW自编程,ATmega88 与ATmega168‖ 。
该位在ATmega48 中无效。
• 位0 – IVCE: 中断向量修改使能改变IVSEL 时IVCE 必须置位。
在IVCE 写入4 个时钟周期或IVSEL 写操作之后,IVC被硬件清零。
如前面所述,置位IVCE 将禁止中断。
代码如下:void Move_interrupts(void){/* 使能中断向量的修改*/MCUCR = (1<<IVCE); /* 将中断向量转移到boot区*/ MCUCR = (1<<IVSEL);}• 位7 – I: 全局中断使能Sei();全局中断使能,cli();对I清零。
• 位6 – T: 位拷贝存储位拷贝指令BLD 和BST 利用T 作为目的或源地址。
AVR 单片机一些学习笔记
下面是自己在学习AVR 单片机时的学习经验,分享出来给大家,一起
学习。
1、AVR 单片机采用RISC 架构,8051 单片机采用CISC 架构。
前者速度为后者的2~4 倍,为流水线操作指令。
2、AVR 单片机有32 个通用寄存器(地址在RAM 区从$0000 开始到$001F),其中有6 个(最后6 个)合并为3 个16 位的X,Y,Z 寄存器,用来存放地址指针,Z 寄存器还可以寻址程序存储器。
3、哈佛结构,131 条机器指令。
4、延迟开机功能。
5、内部自带RC 振荡器,可提供1/2/4/8MHZ 的工作时钟。
6、FLASH+EEPROM+SRAM+SPI+USART+TWI+PWM+RTC+10 位ADC+模拟比较器+JTAG。
7、堆栈指针向下增长,51 单片机向上增长。
8、程序存储器按字来访问,擦除和写入以页为单位。
AVR复习笔记--AVR单片机SPI多机通讯
最近决定复习下AVR 单片机,其实也是为了借此复习下几种简单的通
信协议,包括串口,SPI,I2­C 等。
本来以为一两个晚上就能搞定的事儿,
没想到竟耗费了一周晚上空余的时间。
当然主要是这次的要求要提高点,实现SPI 的多机通信,
不但要发数据还要回传数据。
实际中还是遇到了比我想象中要大的多的困难。
即使是现在的实现方式也不是很理想。
下面是spi 部分的代码,由于spi 接收发送用的同一终端,感觉使用起来形式
不怎么样,还是采用了轮询标志位的方式
Code#include”spi.h”staticcharmode=1;voidspi_init(charflag){chartmp=0;mode=flag; if(mode==1){DDR_SPI=(1 在我的例子中有一个主机,两个从机
进行如下通信
发送至1 号从机1 ,2
发送至2 号从机3 ,4
发送至1 号从机5 ,6
发送至2 号从机7 ,8
从机1 收到数据后回传1
从机2 收到数据后回传2
下面还是看代码
Code#include”basic.h”//自己写的常用函式#include”usart.h”//usart初始化函式
#include”spi.h”intmain(void){chartmp;usart_init(9600);spi_init(1);PORTB|=(1。
A VR学习笔记三、定时/记数器0实验-------基于LT_Mini_M163.1 定时/计数器0的计数实验3.1.1、实例功能定时/计数器(Timer/Counter)是单片机中最基本的接口之一,它的用途非常广泛,常用于计数、延时、测量周期、频率、脉宽、提供定时脉冲信号等。
在实际应用中,对于转速,位移、速度、流量等物理量的测量,通常也是由传感器转换成脉冲电信号,通过使用定时/计数器来测量其周期或频率,再经过计算处理获得。
相对于一般8位单片机而言,AVR不仅配备了更多的定时/计数器接口,而且还是增强型的,如通过定时计数器与比较匹配寄存器相互配合,生成占空比可变的方波信号,即脉冲宽度调制输出PWM信号,用于D/A、马达无级调速控制、变频控制等,功能非常强大。
ATmega16一共配置了2个8位和1个16位,共3个定时/计数器,它们是8位的定时计数器T/C0、T/C2和16位的定时/计数器T/C1。
在接下来的几个实例中,我们将逐一学习这些定时/计数器的各种功能和使用方法。
在前面的实例中,我们已经学习了利用单片机的I/O口进行按键的输入检测,并实现了将按键按下次数在数码管上进行显示。
使用的方法是不停的检测端口状态,每检测到一次电平变化记录一次,这样实现起来未免有些重复劳动的嫌疑,那么有没有一种方法可以不用每次都这么辛苦呢?答案是肯定的!我们可以使用定时/计数器的计数功能实现对外部事件(电平变化次数、脉冲个数等)进行计数。
在本实例中,我们利用ATmega16单片机的定时/计数器0的计数功能实现对按键次数的检测,并通过LED的亮灭来指示程序的运行状态。
本实例共有3个功能模块,分别描述如下:●单片机系统:检测按键的按下,通过LED灯的亮灭指示按键按下次数。
●外围电路:按键检测电路以及显示按键状态的LED显示电路。
●软件程序:熟悉掌握ATmega16单片机的定时/计数器0的计数程序的编写。
3.1.2、器件和原理本实例首先介绍ATmega16单片机的定时/计数器0的功能,然后详细介绍如何利用定时/计数器0实现对外部事件进行计数的功能。
ATmega16中断表第一节课Avr单片机的每个引脚有三个寄存器来控制:DDRnx(输入输出控制寄存器1输出,0输入)PORTnx(引脚输出电平控制)PINnx(输入寄存器)第二节课AVR单片机的AD转换涉及寄存器:ADMUX sbit[7;6]参考电压选择,sbit[5] AD转换数据对齐方式选择,sbit[4:0]通道与增益选择;ADCSRA sbit[7]AD使能,sbit[6]AD开始转换,sbit[5]自动触发使能,sbit[4]AD 中断使能,sbit[3:0]分频设置;SFIOR(触发源的选择)sbit[7:5] (ADTS)选择触发源,ADCL,ADCH数据寄存器;初始化步骤:1:设置通道的IO口为输入(高阻);2:设置与AD有关的寄存器;3:开总中断,SREG=BIT(7);4:写中断函数(中断标号是15)第三节课AVR有三个定时计数器,T/C0,T/C1,T/C2;T/C0,T/C2是两个8BIT的计数器;T/C1定时计数器,普通模式时机寄存器:TCCR1B:2:0时钟选择TCNT1L,TCNTH:定时数据TIMSK :TOIE 中断使能位 使用方法1, 选择时钟源,TCCR1B ;2, 设计初值,TCNT1L ,TCNT1H ;3, 设置中断使能位;TIMSK{2},SREG{7} 4, 选中断号,写中断函数 5, (中断号9)CTC 模式如果输出波形,则设IO 位输出 设置波形模式和时钟源TCCR1B 设置输出模式TCCR1A根据需要设置上限OCR1ATCCR1A 设置输出口频率计算:()A OCR N ffclko112+∙∙=控制寄存器A TCCR1ACOM1A1:0: 通道A 的比较输出模式 COM1B1:0: 通道B 的比较输出模式COM1A1:0与COM1B1:0分别控制OC1A 与OC1B 状态。
如果COM1A1:0(COM1B1:0)的一位或两位 被写入"1”,OC1A(OC1B) 输出功能将取代I/O 端口功能。
此时OC1A(OC1B)相应的输出引脚 数据方向控制必须置位以使能输出驱动器。
定时器模式(2)T/C1 控制寄存器B(TCCR1B)ICNC1: {icnc缩写:input catch noise control}入捕捉噪声抑制器置位ICNC1 将使能输入捕捉噪声抑制功能。
此时外部引脚ICP1 的输入被滤波。
其作用是从ICP1 引脚连续进行4 次采样。
如果4 个采样值都相等,那么信号送入边沿检测器。
因此使能该功能使得输入捕捉被延迟了4 个时钟周期。
ICES1: {input catch (strike)edge select }输入捕捉触发沿选择该位选择使用ICP1 上的哪个边沿触发捕获事件。
ICES 为"0”选择的是下降沿触发输入捕捉;ICES1 为"1”选择的是逻辑电平的上升沿触发输入捕捉。
按照ICES1 的设置捕获到一个事件后,计数器的数值被复制到ICR1 寄存器。
捕获事件还会置为ICF1。
如果此时中断使能,输入捕捉事件即被触发。
当ICR1 用作TOP 值( 见TCCR1A 与TCCR1B 寄存器中WGM13:0 位的描述) 时,ICP1 与输入捕捉功能脱开,从而输入捕捉功能被禁用。
Bit 5 –保留位该位保留。
为保证与将来器件的兼容性,写TCCR1B 时,该位必须写入"0”。
WGM13:2: 波形发生模式见TCCR1A 寄存器中的描述。
CS12:0: 时钟选择这3 位用于选择T/C 的时钟源,时钟选择位描述选择使用外部时钟源后,即使T1 引脚被定义为输出,其1 引脚上的逻辑信号电平变化 仍然会驱动T/C1 计数,这个特性允许用户通过软件来控制计数。
(3)快速PWM使用方法:1,设置端口输出2,设置PWM 模式及时钟模式(操作TCCR1A 和TCCR1B ) 3,设置PWM 频率(操作OCR1A )4,设置占空比(操作OCR1B )()A OCR N f fclko 11+∙=第四节课 串口有关寄存器:UCSRA (状态控制寄存器)、USRB (控制中断寄存器)、USRC (工作模式和数据结构)、UBBRH ,UBBRL (设置波特率)、UDR (数据缓冲器); 初始化方法: 1、 设置工作模式(UCRC ); 2、 波特率设置(UBBRL ,UBBRH ); 3、 使能相关中断; 4、 选择中断号12波特率计算:()18+∙∙=UBRR n baud fclkUSART 控制和状态寄存器 A (UCSRA )RXC: USART 接收结束接收缓冲器中有未读出的数据时RXC 置位,否则清零。
接收器禁止时,接收缓冲器被刷 新,导致RXC 清零。
RXC 标志可用来产生接收结束中断( 见对RXCIE 位的描述)。
TXC: USART 发送结束发送移位缓冲器中的数据被送出,且当发送缓冲器(UDR) 为空时TXC 置位。
执行发送结束中断时TXC 标志自动清零,也可以通过写1 进行清除操作。
TXC 标志可用来产生发送结束中断( 见对TXCIE 位的描述)。
UDRE: USART 数据寄存器空UDRE标志指出发送缓冲器(UDR)是否准备好接收新数据。
UDRE为1说明缓冲器为空,已准备好进行数据接收。
UDRE标志可用来产生数据寄存器空中断(见对UDRIE位的描述)。
复位后UDRE 置位,表明发送器已经就绪。
FE: 帧错误如果接收缓冲器接收到的下一个字符有帧错误,即接收缓冲器中的下一个字符的第一个停止位为0,那么FE 置位。
这一位一直有效直到接收缓冲器(UDR) 被读取。
当接收到的停止位为1 时,FE 标志为0。
对UCSRA 进行写入时,这一位要写0。
DOR: 数据溢出数据溢出时DOR 置位。
当接收缓冲器满( 包含了两个数据),接收移位寄存器又有数据,若此时检测到一个新的起始位,数据溢出就产生了。
这一位一直有效直到接收缓冲器(UDR) 被读取。
对UCSRA 进行写入时,这一位要写0。
PE: 奇偶校验错误当奇偶校验使能(UPM1 = 1),且接收缓冲器中所接收到的下一个字符有奇偶校验错误时UPE 置位。
这一位一直有效直到接收缓冲器(UDR) 被读取。
对UCSRA 进行写入时,这一位要写0。
U2X: 倍速发送这一位仅对异步操作有影响。
使用同步操作时将此位清零。
此位置1可将波特率分频因子从16降到8,从而有效的将异步通信模式的传输速率加倍。
MPCM: 多处理器通信模式设置此位将启动多处理器通信模式。
MPCM置位后,USART 接收器接收到的那些不包含地址信息的输入帧都将被忽略。
发送器不受MPCM设置的影响。
3. USART 控制和状态寄存器B(UCSRB)1001 1000RXCIE: 接收结束中断使能置位后使能RXC中断。
当RXCIE为1,全局中断标志位SREG 置位,UCSRA寄存器的RXC 亦为1时可以产生USART接收结束中断。
TXCIE: 发送结束中断使能置位后使能TXC中断。
当TXCIE为1,全局中断标志位SREG 置位,UCSRA寄存器的TXC 亦为1时可以产生USART发送结束中断。
UDRIE: USART 数据寄存器空中断使能置位后使能UDRE中断。
当UDRIE 为1,全局中断标志位SREG置位,UCSRA寄存器的UDRE 亦为1时可以产生USART数据寄存器空中断。
RXEN: 接收使能置位后将启动USART接收器。
RxD 引脚的通用端口功能被USART功能所取代。
禁止接收器将刷新接收缓冲器,并使FE、DOR及PE标志无效。
TXEN: 发送使能置位后将启动将启动USART发送器。
TxD引脚的通用端口功能被USART功能所取代。
TXEN 清零后,只有等到所有的数据发送完成后发送器才能够真正禁止,即发送移位寄存器与发送缓冲寄存器中没有要传送的数据。
发送器禁止后,TxD引脚恢复其通用I/O功能。
UCSZ2: 字符长度UCSZ2与UCSRC寄存器的UCSZ1:0结合在一起可以设置数据帧所包含的数据位数(字符长度)。
RXB8: 接收数据位8对9位串行帧进行操作时,RXB8 是第9个数据位。
读取UDR包含的低位数据之前首先要读取RXB8。
TXB8: 发送数据位8 对9位串行帧进行操作时,TXB8是第9个数据位。
写UDR之前首先要对它进行写操作。
4. USART 控制和状态寄存器C(UCSRC)UCSRC寄存器与UBRRH寄存器共用相同的I/O地址。
对该寄存器的访问。
URSEL: 寄存器选择通过该位选择访问UCSRC寄存器或UBRRH寄存器。
当读UCSRC时,该位为1 ;当写UCSRC 时,URSEL为1。
UMSEL: USART 模式选择通过这一位来选择同步或异步工作模式。
UMSEL设置UPM1:0: 奇偶校验模式这两位设置奇偶校验的模式并使能奇偶校验。
如果使能了奇偶校验,那么在发送数据,发送器都会自动产生并发送奇偶校验位。
对每一个接收到的数据,接收器都会产生一奇偶值,并与UPM0 所设置的值进行比较。
如果不匹配,那么就将UCSRA 中的PE 置位。
UPM 设置USBS: 停止位选择通过这一位可以设置停止位的位数。
接收器忽略这一位的设置。
USBS 设置UCSZ1:0: 字符长度UCSZ1:0与UCSRB寄存器的UCSZ2结合在一起可以设置数据帧包含的数据位数(字符长度)。
UCSZ 设置UCPOL: 时钟极性这一位仅用于同步工作模式。
使用异步模式时,将这一位清零。
UCPOL 设置了输出数据的改变和输入数据采样,以及同步时钟XCK 之间的关系。
UCPOL 设置5. USART 波特率寄存器(UBRRL 和UBRRH)UCSRC寄存器与UBRRH寄存器共用相同的I/O地址。
对该寄存器的访问。
URSEL: 寄存器选择通过该位选择访问UCSRC 寄存器或UBRRH 寄存器。
当读UBRRH时,该位为0;当写UBRRH时,URSEL为0。
Bit 14:12 –保留位这些位是为以后的使用而保留的。
为了与以后的器件兼容,写UBRRH时将这些位清零。
UBRR11:0: USART 波特率寄存器这个12位的寄存器包含了USART的波特率信息。
其中UBRRH包含了USART波特率高4 位,UBRRL包含了低8位。
波特率的改变将造成正在进行的数据传输受到破坏。
写UBRRL 将立即更新波特率分频器。
DS18B20温度传感器读序列号:向总线发33H 可以读出64位的序列号搜索ROM :发F0H,,用于确定总线上传感器的数量和序列号跳过ROM:发CCH用于对所有的期间操作报警搜索:发ECH启动转换:发44H 转换完成回复1读暂存器的内容:BEH。