AVR_中断系统及应用
- 格式:pdf
- 大小:99.09 KB
- 文档页数:8
利用Code Vision AVR C中断程序实现AVR单片机的TWI读写在AVR单片机的开发过程中,TWI(Two-Wire Interface)总线通信协议是较为常用的一种方式。
我们可以利用CodeVision AVR C中断程序来实现AVR单片机的TWI读写。
首先,我们需要了解一下TWI通信协议的基本原理。
TWI总线上有两条线路,一条为SCL时钟线,另一条为SDA数据线。
两条线路上都有上拉电阻,数据传输时由主机(如AVR单片机)控制SCL时钟线和SDA数据线的电平变化来进行数据传输。
在Code Vision AVR C中,我们可以利用TWI库函数进行TWI通信的操作。
在进行TWI读写时,我们需要先发送起始信号,然后发送设备地址和读写指令,接着进行数据传输,最后发送停止信号。
这一系列操作可以使用TWI库函数中的相应函数来完成。
在使用中断程序时,我们需要使TWI模块开启中断功能,并定义好中断服务程序。
在TWI传输过程中,当一个操作完成后,TWI模块会触发中断,执行相应的中断服务程序。
在中断服务程序中,我们可以处理TWI传输过程中出现的各种情况,如传输完成、传输错误等。
下面以TWI读取一个EEPROM芯片中的数据为例,说明如何利用Code Vision AVR C中断程序实现TWI读写。
假设EEPROM芯片的I2C地址为0xA0,我们需要读取从地址0x00开始的8个字节的数据。
首先,我们需要在程序的头文件中引用Code Vision AVR C提供的TWI库。
#include <mega328p.h>#include <delay.h>#include <twi.h>接着,定义TWI芯片地址和读写指令。
#define EEPROM_WRITE 0xA0#define EEPROM_READ 0xA1定义存储数据的缓冲区。
unsigned char EEPROM_Buffer[8];在主函数中初始化TWI模块,并开启TWI中断。
AN2387使用ATtiny1617上独立于内核的可配置定制逻辑实现夜灯特性•减少CPU使用•使用可配置定制逻辑(Configurable Custom Logic,CCL)模块实现独立于内核的操作•事件系统•TCA0——16位定时器/计数器类型A•SPI0——串行外设接口•AC0——模拟比较器•DAC——数模转换器•EEPROM数据存储器•被动红外探测器•环境光线传感器•16个智能可寻址RGB LED简介本应用笔记介绍了如何使用独立于内核的可配置定制逻辑(CCL)对不同传感器的输入进行滤波以及如何使用Microchip AVR®器件、被动红外(PIR)传感器、环境光线传感器和16个可寻址RGB LED创建特定通信协议。
许多外设被配置为可不依赖于CPU协同工作。
仅当环境足够暗并且PIR传感器前有运动时,灯才会点亮。
该实现使用AVR可配置定制逻辑模块来确定何时发生这种情况。
更新可寻址RGB LED可利用定时器/计数器PWM生成、SPI和CCL来生成特定的单行串行协议。
AN2387目录特性 (1)简介 (1)1.相关器件 (3)1.1.tinyAVR 1系列 (3)2.组件 (4)2.1.STK600 (4)2.2.被动红外探测器 (4)2.3.环境光线传感器 (5)2.4.智能控制LED (5)3.实现 (7)3.1.系统概览 (7)3.2.连接 (7)L配置 (9)3.3.1.LUT0配置 (9)3.3.2.LUT1配置 (10)3.4.程序流 (12)4.从Atmel START获取源代码 (14)5.版本历史 (15)Microchip网站 (16)变更通知客户服务 (16)客户支持 (16)Microchip器件代码保护功能 (16)法律声明 (17)商标 (17)DNV认证的质量管理体系 (18)全球销售及服务网点 (19)相关器件1.相关器件本章列出了本应用笔记的相关器件。
1.1 tinyAVR 1系列下图给出了tinyAVR® 1系列,绘制了不同引脚数型号与存储器大小的关系:•垂直向上移植无需修改代码,因为这些器件的引脚彼此兼容,可提供相同甚至更多的功能。
AVR 定时器中断初值计算方法使用芯片AT Mega16 外部晶振定时器1 (16位定时器)寄存器TCCR1B = 0x04 设定256预分频要利用定时器定时1秒1,4000000 / 256 = 15625 说明定时器每当1/15625 秒就会触发一次中断2,65535 - 15625 = 49910 计算出要累加多少次才能在1秒后出发定时器1的溢出中断3,49910 <==> C2 F6 将计算后的值换算成16进制4,TCNT1H = 0xC2 ; 对寄存器赋值TCNT1L = 0xF6 ;=================================================例如用16位定时器TIMER1,4MHZ晶振,256分频,100ms定时,如何求得初值赋给TCNT165536-(4M/256)*=其中,4M是晶体频率,是定时时长单位秒。
对于8位的定时器T=(2^8-计数初值)*晶振周期*分频数=(2^8-计数初值)/晶振频率*分频数计数初值=2^8-T/晶振周期/分频数=2^8-T*晶振频率/分频数因为AVR一指令一周期IAR For AVR 精确延时C语言中,想使用精确的延时程序并不容易。
IAR 中有这样的一个函数__delay_cycles(),该函数在头文件中定义,函数的作用就是延时N个指令周期。
根据这个函数就可以实现精确的延时函数了(但不能做到100%精确度)。
实现的方法:建立一个的头文件:#ifndef __IAR_DELAY_H#define __IAR_DELAY_H#include <>#define XTAL 8 //可定义为你所用的晶振频率(单位Mhz)#define delay_us(x) __delay_cycles ( (unsigned lon g)(x * XTAL) )#define delay_ms(x) __delay_cycles ( (unsigned lon g)(x * XTAL*1000) )#define delay_s(x) __delay_cycles ( (unsigned long )(x * XTAL*1000000) )#endif注意:__delay_cycles(x),x必须是常量或则是常量表达式,如果是变量则编译报错!关于溢出中断不管是哪个单片机都是不断累加,使其寄存器溢出触发中断,然后跳转到中断函数处执行中断服务程序。
关于溢出中断不管是哪个单片机都是不断累加,使其寄存器溢出触发中断,然后跳转到中断函数处执行中断服务程序。
对于定时器初值的设定可以加深对定时器的工作原理的理解。
ATMega16 里面有8位和16位两种定时器,他们何时会溢出这个是固定的,也就是到达他们的计数范围的最大值就会产生中断,8位的定时器的最大计数范围是0~256(2的8次方),就是累加到256后他就会产生中断,16位的定时器最大计数范围是0~65536(2的16次方),累加到65536时他就会产生中断。
而我们所谓的计数初值是就是要设定定时器在什么地方开始计数,以8位定时器为例比如:初值为100,所以定时器从100开始累加,累加了156次,加到256后产生中断,这就是中间消耗的时间和指令周期就是我们要去设定的时间;再比如:初值是200,所以定时器从200开始累加,累加了56次,加到256后产生中断,可以看到第一定时要累加156次才会中断而第二次只要累加56次就会产生中断,显然第一次设定的时间要比第二次的长。
定时器不仅可以定时,而且我们用到定时器的时候往往是需要精确定时的时候。
我们可以计算出我们设定的初值会在多长时间后进入中断。
下面的是8位定时器设定的时候需要用的寄存器:实验平台:ATMega16晶振: 11.0592 MHz对初值的计算:1,11059200 / 1024 = 10800 设定为1024倍分频,得到每1秒需要进行多少次累加2,10800 / 100 = 108 得到10ms 的定时需要进行多少次累加(第一步计算出每一秒进行的累加次数,由于一秒是100个10ms,故除数为100)3,256 - 108 = 148 计算范围最大值(8位寄存器)减去要累加的时间,得到初值,即从哪里开始累加才能在溢出时为10ms的时间。
4,148 <==> 0x94 得到十六进制值,赋值给TCNT0#实验代码:定时10ms_ICCAVR#include <iom16.h>unsigned char flag = 0;void timer_init(void){TCCR0 = 0x05; //进行1024分频TCNT0 = 0x94; //赋计数初值TIMSK_TOIE0 = 1; //开使能SREG_I = 1; //开总中断}#pragma vector = TIMER0_OVF_vect__interrupt void time0_normal(void){TCNT0 = 0x94; //重新赋初值flag++;}void main(void){timer_init();DDRB_Bit0 = 1;while(1){if(flag == 100) //10ms 重复100次,即为1秒 {PORTB_Bit0 = ~PORTB_Bit0; //让LED闪烁flag = 0;}}}//+++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++//实验平台:ATMega16晶振:11.059216位定时器初值设定:1,11059200 / 256 = 43200 设定256倍分频,得到每1秒需要进行多少次累加2,65536 - 43200 = 22336 计算范围最大值减去要累加的时间,得到初值,即从哪里开始累加才能在溢出时为1s的时间。
IAR A VR使用说明总结(以IAR for A VR 5.11B A VR M16为例)iar 是目前编译效率较高的编译器,支持软件仿真和实事仿真,包括简易版M16版jtag ice 。
软件可以从iar官方网站下载使用,demo version 30 days 全功能使用,目前所谓破解版一般是这个版本的破解。
废话不讲了,以m16为例,解释IAR的使用,软件版本5.11b, 30天限制版,希望和大家共同学习IAR FOR A VR 。
IAR A VR使用说明总结(以IAR for A VR 5.11B A VR M16为例)1.新建一个开发环境的1.1单击[IAR Embedded Workbench]图标,选择[Project] / [Create New Project ...], 参考下图1.2设置[Tool chain]选择[A VR];设置[Project templates]选择[Emply project];然后单击[OK],参考下图1.3保存设置,选择保存路径和文件名, 参考如下1.4工具的基本设置,单击[Tool] / [Options], 参考如下1.5单击[Configure], 参考如下1.6工程设置,单击[Project] / [Options],1.7[General Options]选项1.7.1[target]选项卡,[Processor configuation]选择目标mcu, 参考如下1.7.2[Output]选项卡,输出文件设置,选择[Executable], 参考如下1.7.3[Library Configuration]选项卡,[Library]设置,选择[CLIB], 参考如下1.8[C/C++ Compiler]选项1.8.1[Language]选项卡参考如下1.8.2[Optimizations]选项卡参考如下1.8.3[Output]选项卡参考如下1.8.4[List]选项卡参考如下1.9[Linker] 选项卡控制输出文件格式1.10[Debugger] 选项卡, 设置仿真工具,[Simulator]软件仿真,[JTAGEIC]JTAG仿真,参考如下1.11[JTAGICE] 选项卡设置JTAG选项1.12单击[OK],完成设置1.13保存工程设置单击[File] / [save workspace], 选择保存路径和文件名1.14添加文件到工程单击[Project] / [add files], 选择文件,然后单击[OK]2生成可烧写文件(*.hex 和*.eep ,以IAR for A VR 5.11B/W32 (5.11.2.5) 和M16为例)2.1配置[Linker] 选项卡, 在[Format]选择[other],[Output format]选择[ubrof 6 (forced) ],参考下图2.2查看*.xcl文件2.2.1在可以[config]选项卡中看到,如下图红色方框中所示为”cfgm16.xcl’(不同mcu对应的*.xcl文件不同), 默认路径为C:\Program Files\IAR Systems\Embedded Workbench5.0 Evaluation\avr\src\template2.2.2修改次文件, 在“*.xcl”文件末,添加下面两行代码-Ointel-extended,(CODE)=.hex-Ointel-extended,(XDATA)=.eep2.2.3数据定义在eeprom中,使用关键词”__eeprom”, 但是需要增加前前缀”__root”, 使用方法, 参考如下如下__root __eeprom unsigned char table[]={0,1,2,2,3,4};__root __eeprom unsigned char tablex[] @0x10 ={10,11,12,12,13,14}; //绝对地址定义2.定义数到flash空间,使用关键词”__flash” , 使用方法, 参考如下如下__flash unsigned char tablex []={1,2,2,3,4,5,6}__flash unsigned char tablex []@0x10={1,2,2,3,4,5,6} //绝对地址定义3.关键词”__root”功能保证没有使用的函数和变量也能够包含在目标代码中,定义放在flash 空间的数据,在程序编译时会自动生成代码嵌入到flash代码中,对于程序没有使用的也要求编译的数据,必须加入关键词” __root”,编译器才会输出目标代码。