您好,欢迎来到抵帆知识网。
搜索
您的当前位置:首页AVR??

AVR??

来源:抵帆知识网
软件延时很简单,就是让CPU在那里跑来跑去就行了。

不过延时时间就很难给出一个算法了,晶振频率、循环次数、变量类型、语法等,特别是语法只要有一点不同延时结果就大不相同。

下面给你一个简单的原型,里面的计数参数你可以先填一个值,然后在AVR STUDIO时面仿真对结果,这样就能找到一个合适的值。

/* 延时函数 */

void delay_ms(unsigned int i) {

unsigned int a, b;

for (a = 0; a < i; a++) {/*这个for循环用于处理延时单位*/ for (b = 0; b < 参数; b++) {/*这个for循环产生1mS的延时*/ ; } } }

还有这一种写法

void DelayMs(long int i) { int t; while(i--) {

for(t=1000;t>0;t--) ; } }

不同晶体的通用延时函数:

void delay_ms(unsigned int time) {

unsigned int i; for(;time;time--)

{

for (i=1;i<(unsigned int) (xtal*143-2);i++) ; } }

不同晶体的通用延时函数:

void delay_ms(unsigned int time) {

unsigned int i; for(;time;time--) {

for (i=1;i<(xtal*143-2);i++) ; } }

xtal为晶振,time为延时的ms值.

请教各位仁兄:我atmega88的定时器不工作,初始化及中断程序如下: #define Signal _VECTOR(11) void Timer1_init() {

TIMSK1=0x80; TCCR1B=0x00; TCNT1L=0xF9; TCNT1H=0xE6; TCCR1A=0x00; TCCR1B=0x05; _SEI(); }

void Signal(_VECTOR(11))

{

unsigned int Count; Count++; TCNT1L=0xF9; TCNT1H=0xE6; if(Count==4) { Count=0;

PORTB^=(1<希望大家能给指点一下,谢谢!

谢谢各位仁兄,是没开定时器中断,应该把“TIMSK1=0x80“改为“TIMSK1=0x01“;还有中断向量号也弄错了,应该把“_VECTOR(11)“改为“_VECTOR(13)“。 其实定时器是非常简单的,就是乘除法: 1、分频值 * 计数值 = 总计数值。 2、总计数值 * 计数单位时间 = 延时时间。

同样实现延时10mS,直接让OCR1A = 10 000,1分频也是同样的效果。 我的板子是采用M16,晶振16M,以下是t0初始化。 void dispinit(void) {

TCNT0=255-250; //赋初值

//TCCR0=0b111; //时钟为CK/1024,向上计数器 M64适应 TCCR0=0b101; //时钟为CK/1024,向上计数器 M16适应 TIMSK|=(1<#pragma interrupt_handler timer0_ovf: 10 void timer0_ovf(void) {

PORTD^=(1<<4); TCNT0=255-250; }

调试的时候pd4灯没有反应,请大家帮我看哪里出问题了?

AVRBBS:问题找到了(中断向量号),楼主用M32代替M16使用,刚好M32和M16的不同点正是中断向量号。呵呵是我们一起被M32忽悠了。 void delay_ms(unsigned int i) { unsigned int a; unsigned char b;

for (a = 1; a < i; a++) { for (b = 1; b; b++) { ; } } }

其使用的是1M晶振

上面程序是大概时间,CPU为1MHz频率,一个单位延时1mS。

1mS延时由内部的for循环实现的,根据变量b的值域,0-255,for循环能循环255次,这个for计时变量是字符型的,以这种方式判断一次大概要花4个CPU周期。 1M的频率,CPU一个周期也就是1uS。

那么这个循环所用的全部时间:255 * 4 大约就是1000次,也就约等于1000uS = 1mS。

for 循环的变量类型不同,判断语法不同,循环一次所用的CPU周期都有很大差别。上面4个周期是对C语言语句的了解,了解它在转为汇编后所对应的语句,而汇编语句所占用的CPU周期,经过这样一个过程推断出来的。

C语言最终都会转变为相应的汇编语句,如果我们非常了解C语言了解汇编语言,并了解它们之间的等同性,那你就可以大概估算出一条C语句所占用的时间了。

一般新手都不具有这个经验,所以最好的方法是用软件仿真的方式,看看循环一次到底要多少时间,这样一来二往的,就有了经验了。

请问各位大侠! 8M的晶振, 64分频 TCNT0= ?; 计数寄存器的初始值是多少? 怎么计算的呢? 一次中断的时间是: T = (256-TCNT0) * 64 / 8MHz

按这公式算。要知道 TCNT0 是多少,得先确定你一次中断的 T 。 基于定时器1输入捕捉功能做的一个频率计

Post By:2007-6-19 16:20:00

//ICC-AVR application builder : 2007-6-19 下午 04:14:03 // Target : M16 // Crystal: 11.059Mhz #include #include #include \"stdio.h\" unsigned int Freq = 0;

//TIMER1 initialize - prescale:1024 void timer1_init(void) {

TCCR1B = 0x00; //stop TCNT1H = 0xD5; //setup TCNT1L = 0xD1; ICR1H = 0x2A; ICR1L = 0x2F; TCCR1A = 0x00;

TCCR1B = 0xC5; //start Timer }

#pragma interrupt_handler timer1_capt_isr:6

void timer1_capt_isr(void) { Freq++; }

#pragma interrupt_handler timer1_ovf_isr:9 void timer1_ovf_isr(void) {

TCNT1H = 0xD5; TCNT1L = 0xD1; printf(\"%d\ Freq = 0;

while(!(UCSRA&0x20)); UDR = 0x0d; }

// desired baud rate: 9600 void uart0_init(void) {

UCSRB = 0x00; //disable while setting baud rate UCSRA = 0x00;

UCSRC = BIT(URSEL) | 0x06; UBRRL = 0x47; //set baud rate lo UBRRH = 0x00; //set baud rate hi UCSRB = 0x18; }

void init_devices(void) {

CLI(); //disable all interrupts timer1_init(); uart0_init();

MCUCR = 0x00; GICR = 0x00;

TIMSK = 0x24; //timer interrupt sources SEI(); //re-enable interrupts }

void main(void) {

init_devices(); while(1); }

工作原理: 1、触发源

输入捕捉单元的主要触发源是ICP1。T/C1 还可用模拟比较输出作为输入捕捉单元的触发源。在这里我用的是外部输入的脉冲序列来实现触发 2、触发信号

触发信号是边沿信号,可以是上升沿触发也可以是下降沿触发。值得一提的是,我们可以利用它的两个边沿触发来实现脉宽的测量。具体的原理是上升沿触发获得一个计数值,然后把触发条件再改为下降沿。接着再在下降沿获得一个计数值。这个值是通过读取ICR1来获得的,这就涉及到了3 3、输入捕捉寄存器ICR1

ICR1存储的是当输入信号被捕捉到的时候TCCNT的当前值。ICR1的值需要尽快的读出。当一次新的触发信号发生并被捕捉到时。新的值将覆盖原来ICR1寄存器中的值。

4、在本例程中,我只是通过计数的方式实现频率计,未对ICR1涉及到读写操作。如果需要测量脉宽和相位,则需要用到ICR1。 5、关于TIMSK

使能输入捕捉功能需要将TICIE1置位

6、第一次使用输入捕捉功能,难免有理解上的错误,希望大家不吝赐教

我用这个思想做了一个10ms定时中断程序,嵌套一个1ms定时中断的程序.可是运行后没有达到效果,请大家帮我看一下:

void init_devices(void) //中断初始化 {

CLI(); //disable all interrupts

TIMSK = 0x05; //TIMER1溢出中断使能 TCCR1B= 0x00; //先停止TIMER1 TCNT1H= 0xff; //10ms定时初值 TCNT1L= 0x83; TCCR1A= 0x00; TCCR1B=0x03; //64分频

TCNT0=0xb2; //计数值初值 TCCR0=0x05; //CK/1024

SEI(); //enable all interrupts }

#pragma interrupt_handler timer0_isr:10 void timer0_isr(void) //10ms中断服务程序 {

TIMSK=0x01; //屏蔽除A外的其它中断允许 SEI(); //允许全局中断 TCNT0=0xb2; //计数值清零 TCCR0=0x05; //CK/1024 led_display ();//10ms中断服务程序 CLI();

TIMSK=0x05; //恢复10ms中断 }

#pragma interrupt_handler timer1_isr:9 void timer1_isr(void) //1ms中断服务程序 {

TCNT1H=0xff;

TCNT1L=0x83; count++; }

//此程序为AVR外部中断,时钟中断,串行通信,IIC综合实例 #include #include

#define uchar unsigned char #define uint unsigned int

#pragma interrupt_handler int2:19//外部中断2

#pragma interrupt_handler timer0_ovf_isr:10//时钟中断 #pragma interrupt_handler rec:12//串口接收中断 void delay(uint ticks);//延时

unsigned char const Tab[]={0x14,0x9F,0x38,0x1A,0x93,0x52,0x50,0x1F, 0x10,0x12,0x11,0xD0,0x74,0x98,0x70,0x71}; //数码管显示代码

unsigned int count=0;//软件记数 void main() {

uchar Address,date; int x=0,j=0; init_devices(); //中断设置

CLI();//关总中断 //INT2设置

MCUCSR&=~0x40;//下降沿触发 GIFR|=0x20;//清INT2标志 GICR|=0x20;//开INT2中断 //定时设置

TCCR0 = 0x00; //stop

TCNT0 = 0x83; //set count OCR0 = 0x7D; //set compare //TCCR0 = 0x03; //start timer

TIMSK = 0x01; //timer interrupt sources //串口设置,波特率:9600

UCSRB = 0x00; //disable while setting baud rate UCSRA = 0x00;

UCSRC = BIT(URSEL) | 0x06;

UBRRL = 0x33; //set baud rate lo UBRRH = 0x00; //set baud rate hi //UCSRB = 0x08;

UCSRB = (1<PORTA=0x80; PORTC=Tab[8];

//DS3231每秒产生一个中断:

WriteDs3231_OneByte(0x0e,0x07);

WriteDs3231_OneByte(7,0x80);WriteDs3231_OneByte(8,0x80); WriteDs3231_OneByte(9,0x80);WriteDs3231_OneByte(10,0x81); /*

while(1)

{//读出并显示:

date=ReadDs3231_OneByte(j++);//读取数据

if(j==7)j=0;//循环读出00-06地址的数据:秒、分、时、星期、日期、月和年信息

for(x=0;x<200;x++) {

PORTA=0x80;

PORTC=Tab[date&0x0f];//显示个位 delay(50); PORTA=0x40;

PORTC=Tab[date>>4];//显示十位 delay(50); }

PORTA=0;//关闭显示 delay(5000); }*/ }

void delay(uint ticks) {

uchar i;

while(ticks--)for(i=100;i!=0;i--);//约0.1mS }

void int2()//外部中断服务程序 {

CLI();

PORTC=Tab[ReadDs3231_OneByte(0)&0x0f]; SEI(); }

void timer0_ovf_isr(void)//定时中断服务程序 {

unsigned char data;

TCNT0 = 0x83; //reload counter value if(++count==3000)//1000个1mS等于1秒 {

count=0;

data=ReadDs3231_OneByte(0)&0x0f; PORTC=Tab[data]; printf(\"%dn\ } }

void rec()//接收中断服务程序 {

unsigned char data; data=UDR; PORTC=data; }

下面给出一个参考程序:程序在ICCAVR调试通过,仿真proteus 7.0通过

/******************************** 文件名 INT0.c

功能: 外部中断0.1 作者; 漂洋过海

时间; 2008年七月14日早8:08 目标: MCU MEGA8(L) 晶振: 内部振荡

*********************************/ #include\"iom8v.h\" #include\"macros.h\"

#define uchar unsigned char #define uint unsigned int uchar Count;

void init() {

DDRB=0xff;

PORTB=0X00;//点亮所有发光二极管 DDRD=0Xfc; PORTD=0XFF;

//MCUCR|=(1<MCUCR|=(1<//MCUCR|=(1<GICR|=(1<GIFR=0x00;//中断标志位清零 SEI(); }

void main() {

init(); while(1) { ; } }

/********************************

外部中断0和1公共用同一个中断服务函数 *********************************/ #pragma interrupt_handler int_fun:2 #pragma interrupt_handler int_fun:3 void int_fun() {

Count++;

PORTB=Count; }

//ICC-AVR application builder : 2006-12-8 17:04:44 // Target : M16

// Crystal: 7.3728Mhz

#include #include

unsigned int i=0;

void port_init(void) {

PORTA = 0x00; DDRA = 0x01; PORTB = 0x00; DDRB = 0x00;

PORTC = 0x00; //m103 output only DDRC = 0x00;

PORTD = 0x0C; //使INT0,INT1对应口上拉电阻有效 DDRD = 0x00; //必须设置INT0,INT1对应口为输入 }

#pragma interrupt_handler int0_isr:2

void int0_isr(void) {

//external interupt on INT0 i++; //在中断里进行操作 }

#pragma interrupt_handler int1_isr:3 void int1_isr(void) {

//external interupt on INT1

PORTA = 0x01; //在中断里进行操作 }

//call this routine to initialize all peripherals void init_devices(void) {

//stop errant interrupts until set up CLI(); //disable all interrupts port_init();

MCUCR = 0x08; //INT1 的下降沿产生异步中断请求,INT0上升延 GICR = 0xC0; //INT0和INT1使能

TIMSK = 0x00; //timer interrupt sources SEI(); //re-enable interrupts

//all peripherals are now initialized }

void main(void) {

init_devices();

while(1) //死循环等待中断 ; }

C中断向量:

#if defined(_ICC_AVR_) // \"ICCAVR 编译器\"条件编译开始 /*======================================================================================

中断向量定义

======================================================================================*/

#define IT_RESET 1

// 外部引脚、上电复位、掉电检测复位、看门狗复位、以及 JTAG AVR 复位中断向量

#define IT_INT0 2 // 外部中断请求0中断向量 #define IT_INT1 3 // 外部中断请求1中断向量

#define IT_TIMER2_COMP 4 // 定时器/计数器2比较匹配中断向量

#define IT_TIMER2_OVF 5 // 定时器/计数器2溢出中断向量 #define IT_TIMER1_CAPT 6 // 定时器/计数器1输入捕获中断向量

#define IT_TIMER1_COMPA 7 // 定时器/计数器1A比较匹配中断向量

#define IT_TIMER1_COMPB 8 // 定时器/计数器1B比较匹配中断向量

#define IT_TIMER1_OVF 9 // 定时器/计数器1溢出中断向量 #define IT_TIMER0_OVF 10 // 定时器/计数器0溢出中断向量 #define IT_SPI_STC 11 // SPI串行传输结束中断向量 #define IT_USART_RXC 12 // USART接收结束中断向量 #define IT_USART_UDRE 13 // USART数据寄存器空中断向量

#define IT_USART_TXC 14 // USART传送结束中断向量 #define IT_ADC 15 // ADC转换结束中断向量 #define IT_EE_RDY 16 // EEPROM就绪中断向量 #define IT_ANA_COMP 17 // 模拟比较器中断向量 #define IT_TWI 18 // 两线串行接口中断向量 #define IT_INT2 19 // 外部中断请求2中断向量

#define IT_TIMER0_COMP 20 // 定时器/计数器0比较匹配中断向量

#define IT_SPM_RDY 21 // 保存程序存储器内容就绪中断向量

#endif // \"_ICC_AVR_\" 条件编译结束

#if defined(_CodeVision_AVR_) // \"CodeVision AVR C 编译器\"条件编译开始

#define EXT_INT0 2 // 外部中断请求0中断向量 #define EXT_INT1 3 // 外部中断请求1中断向量

#define TIM2_COMP 4 // 定时器/计数器2比较匹配中断向量 #define TIM2_OVF 5 // 定时器/计数器2溢出中断向量

#define TIM1_CAPT 6 // 定时器/计数器1输入捕获中断向量 #define TIM1_COMPA 7 // 定时器/计数器1A比较匹配中断向量 #define TIM1_COMPB 8 // 定时器/计数器1B比较匹配中断向量 #define TIM1_OVF 9 // 定时器/计数器1溢出中断向量 #define TIM0_OVF 10 // 定时器/计数器0溢出中断向量 #define SPI_STC 11 // SPI串行传输结束中断向量 #define USART_RXC 12 // USART接收结束中断向量 #define USART_DRE 13 // USART数据寄存器空中断向量

#define USART_TXC 14 // USART传送结束中断向量 #define ADC_INT 15 // ADC转换结束中断向量 #define EE_RDY 16 // EEPROM就绪中断向量 #define ANA_COMP 17 // 模拟比较器中断向量 #define TWI 18 // 两线串行接口中断向量 #define EXT_INT2 19 // 外部中断请求2中断向量

#define TIM0_COMP 20 // 定时器/计数器0比较匹配中断向量 #define SPM_READY 21 // 保存程序存储器内容就绪中断向量

#endif // \"defined(_CodeVision_AVR_)\" 条件编译结束

#if defined(_IAR_EW_AVR_) // \"IAR Embedded Workbench AVR 编译器\"条件编译开始

#define RESET_vect (0x00)

// 外部引脚、上电复位、掉电检测复位、看门狗复位、以及 JTAG AVR 复位中断向量

#define INT0_vect (0x04) // 外部中断请求0中断向量 #define INT1_vect (0x08) // 外部中断请求1中断向量 #define TIMER2_COMP_vect (0x0C) // 定时器/计数器2比较匹配中断向量

#define TIMER2_OVF_vect (0x10) // 定时器/计数器2溢出中断向量

#define TIMER1_CAPT_vect (0x14) // 定时器/计数器1输入捕获中断向量

#define TIMER1_COMPA_vect (0x18) // 定时器/计数器1A比较匹配中断向量

#define TIMER1_COMPB_vect (0x1C) // 定时器/计数器1B比较匹配中断向量

#define TIMER1_OVF_vect (0x20) // 定时器/计数器1溢出中断向量

#define TIMER0_OVF_vect (0x24) // 定时器/计数器0溢出中断向量

#define SPI_STC_vect (0x28) // SPI串行传输结束中断向量 #define USART_RXC_vect (0x2C) // USART接收结束中断向量 #define USART_UDRE_vect (0x30) // USART数据寄存器空中断向量

#define USART_TXC_vect (0x34) // USART传送结束中断向量 #define ADC_vect (0x38) // ADC转换结束中断向量 #define EE_RDY_vect (0x3C) // EEPROM就绪中断向量 #define ANA_COMP_vect (0x40) // 模拟比较器中断向量 #define TWI_vect (0x44) // 两线串行接口中断向量 #define INT2_vect (0x48) // 外部中断请求2向量

#define TIMER0_COMP_vect (0x4C) // 定时器/计数器0比较匹配中断

向量

#define SPM_RDY_vect (0x50) // 保存程序存储器内容就绪中断向量

#endif // \"defined(_IAR_EW_AVR_)\" 条件编译结束

汇编语言中断向量:

;*************************************************************************

;* 中断向量位置声

明 *

;*************************************************************************

;******** 中断向量地址定义:

.equ INT0addr = 0x002 ;外部中断请求0向量地址 .equ INT1addr = 0x004 ;外部中断请求1向量地址

.equ OC2addr = 0x006 ;定时器/计数器2比较匹配中断向量地址

.equ OVF2addr = 0x008 ;定时器/计数器2溢出中断向量地址 .equ ICP1addr = 0x00a ;定时器/计数器1输入捕获中断向量地址

.equ OC1Aaddr = 0x00c ;定时器/计数器1A比较匹配中断向量地址

.equ OC1Baddr = 0x00e ;定时器/计数器1B比较匹配中断向量地址

.equ OVF1addr = 0x010 ;定时器/计数器1溢出中断向量地址 .equ OVF0addr = 0x012 ;定时器/计数器0溢出中断向量地址 .equ SPIaddr = 0x014 ;SPI串行传输结束中断向量地址 .equ URXCaddr = 0x016 ;USART接收结束中断向量地址 .equ UDREaddr = 0x018 ;USART数据寄存器空中断向量地址

.equ UTXCaddr = 0x01a ;USART传送结束中断向量地址 .equ ADCCaddr = 0x01c ;ADC转换结束中断向量地址 .equ ERDYaddr = 0x01e ;EEPROM就绪中断向量地址 .equ ACIaddr = 0x020 ;模拟比较器中断向量地址 .equ TWIaddr = 0x022 ;两线串行接口中断向量地址 .equ INT2addr = 0x024 ;外部中断请求2向量地址

.equ OC0addr = 0x026 ;定时器/计数器0比较匹配中断向量地址

.equ SPMRaddr = 0x028 ;保存程序存储器内容就绪中断向量地址

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- dfix.cn 版权所有

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务