AVR 代码练习.docx
《AVR 代码练习.docx》由会员分享,可在线阅读,更多相关《AVR 代码练习.docx(21页珍藏版)》请在冰豆网上搜索。
![AVR 代码练习.docx](https://file1.bdocx.com/fileroot1/2023-1/27/757f09c6-3465-432b-8905-1b9e4c6b55c9/757f09c6-3465-432b-8905-1b9e4c6b55c91.gif)
AVR代码练习
1.简单IO口操作
/*
DDRx(x是指的是A,B,C,D四组io口)是方向寄存器?
当DDR=1时,设定其为输出功能,
当DDR=0的时候,设设定其为输入功能
PORTx=0xff时,使得x这组Io口输出电平为高电平
头文件是#include
*/
#include
voidmain()
{
DDRB=0xff;//LEDconnectwithPBport;
PORTB=0xaa;
while
(1)
;
}
2.三种位操作方式
/*
#include位操作头文件
位操作有三种方式
DDRB|=(1<<3)让B组IO口的第三位置1
DDRB|=BIT(3);
DDRB|=BIT(DDRB3)
*/
//利用三种方法实现三个灯灭
#include
#include
voidmain()
{
DDRB=0xff;//让PB处于输出功能
PORTB=0x00;//熄灭所有的LED
PORTB|=(1<<2);//让PB的第二个端口点亮
PORTB|=BIT(3);//点亮第三个LED
PORTB|=BIT(PORTB4);//点亮第四个LED
while
(1);
}
3.与或、异或、独立按键等操作
/**************知识总结:
*************************
1.按位异或PORTA^=0x80实现最高位翻转的功能
2.判断输入的电平if(PINA&0X80)判断最高位是否为1
*************************************************/
#include
#include
voiddelay()
{
unsignedinti,j;
for(i=0;i<240;i++)
for(j=0;j<240;j++);
}
voidmain()
{
//实现LED闪烁的功能
DDRB=0xff;//PB输出
/*
方法一:
while
(1)
{
PORTB|=0xff;
delay();
PORTB&=0x00;
delay();
}
方法二:
while
(1)
{
PORTB^=0xff;//这里是对PB端口所有的位都进行异或操作
delay();
}
*/
//按键控制LED的亮灭
DDRC=0x00;//定义PC端口为输入状态
PORTC=0xff;//如果PC当做输入使用的时候,若PORTC=0xff,则输入时带有
//上拉电阻的,若PORTC=0x00的时候,是高阻态
//当DDRC定义为输出状态的时候,无论PORTC为0还是1都无上拉
while
(1)
{
if(PINC&0x80)//连接PA第一个端口的按键按下
{
PORTB=0x55;
}
else
{
PORTB=0xaa;
}
}
}
4.蜂鸣器
//按键控制蜂鸣器
#include
#include
voiddelay()
{
unsignedinti,j;
for(i=0;i<240;i++)
for(j=0;j<10;j++);
}
voidmain()
{
DDRB=0xff;//定义PB为输出
DDRC=0x00;//定义PC为输入(接按键)!
!
!
while
(1)
{
if(PINC&0x01)//按键没有按下!
!
!
{
PORTB|=BIT(0);//将PB0置位
}
else
{
while
(1)
{
PORTB^=0x01;//拉低beep的端口,打开蜂鸣器
delay();
}
}
}
}
5.流水灯
#include
#include
#defineuintunsignedint
#defineucharunsignedchar
uchartable[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
voiddelay()
{
uchari,j;
for(i=0;i<240;i++)
for(j=0;j<240;j++)
;
}
voidmain()
{
uchari;//控制哪个LED亮
DDRB=0xff;//PB输出
DDRC=0x00;//PC输入
while
(1)
{
//方法一:
利用总线的方法实现流水灯
PORTB=0x01;
for(i=0;i<8;i++)
{
PORTB=table[i];
delay();
}
//方法二:
利用位操作的方式实现
PORTB=0x00;//关闭所有的LED
for(i=0;i<8;i++)
{
PORTB|=BIT(i);
delay();
PORTB&=~BIT(i);
}
//方法三:
对某一位进行翻转
PORTB=0x00;
for(i=0;i<8;i++)
{
PORTB^=BIT(i);//由于初始化的时候全部是0x00,对某一引脚进行翻转0->1
delay();
PORTB^=BIT(i);//1->0再次回到初始状态
}
}
}
6.数码管
#include
#include
#defineuintunsignedint
#defineucharunsignedchar
uchartable[16]=
{0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
ucharsmg_bit[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
voiddelay()
{
uchari,j;
for(i=0;i<10;i++)
for(j=0;j<10;j++);
}
voidInitPort()
{
DDRA=0xff;
PORTA=0xff;
DDRB=0xff;
PORTB=0xff;
}
voidmain()
{
uchardisp_num;
ucharcount;
ucharbai,ge,shi;
count=0;
disp_num=0;
InitPort();
while
(1)
{
if(++count==20)
disp_num++;
bai=disp_num/100;
shi=disp_num%100/10;
ge=disp_num%10;
PORTA=table[bai];
PORTB=smg_bit[0];
delay();
PORTA=table[shi];
PORTB=smg_bit[1];
delay();
PORTA=table[ge];
PORTB=smg_bit[2];
delay();
}
}
7.外部中断
/************************************************
voidInitInt0(void)
{
MCUCR|=0x02;//设置中断触发方式(中断0的下降沿触发)
GICR|=BIT(6);//打开外部中断0
SREG|=BIT(7);//打开全局中断
}
DDRD&=~BIT
(2);//让接按键的引脚设置为输入状态
PORTD|=BIT
(2);//设置该引脚有上拉电阻
将开关接到PD2上面
*************************************************/
#include
#include
#defineuintunsignedint
#defineucharunsignedchar
voiddelay(void)
{
uchari,j;
for(i=0;i<200;i++)
for(j=0;j<200;j++);
}
voidInitPort(void)
{
DDRA=0xff;
PORTA=0;//初始时让LED全部熄灭
DDRD&=~BIT
(2);//让接按键的引脚设置为输入状态
PORTD|=BIT
(2);//设置该引脚有上拉电阻
}
voidInitInt0(void)
{
MCUCR|=0x02;//设置中断触发方式(中断0的下降沿触发)
GICR|=BIT(6);//打开外部中断0
SREG|=BIT(7);//打开全局中断
}
voidmain(void)
{
InitPort();
InitInt0();
while
(1)
{
PORTA^=0xff;
delay();
}
}
#pragmainterrupt_handlerint0_isr:
2
voidint0_isr(void)
{
PORTA^=BIT
(1)+BIT
(2)+BIT(4)+BIT(3);//!
!
!
delay();
delay();
delay();
delay();
delay();
delay();
}
8.ADC(未能测试)
/*******************************************
*1.ADC输入端口初始化
*2.基准电压设置,数据对齐方式,通道选择(ADMUX)
*3.AD使能,启动转换,及中断设置(ADCSRA)
*4.触发源选择(SFIOR)
*选择中断号,编写中断服务程序,读取ADC转换结果(ADCH,ADCL)
*注意是BCD码,也就是16进制
功能:
调节电阻,查看转换后的值的大小
******************************************/
#include
#include
#defineuintunsignedint
#defineucharunsignedchar
uchartable[16]=
{0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
ucharsmg_bit[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
voiddisp(intdisp_num);
voiddelay()
{
uchari,j;
for(i=0;i<200;i++)
for(j=0;j<200;j++)
;
}
voidInitPort()
{
DDRA=0x00;//输入模式
DDRB=0xff;//显示数码管用,下同
DDRC=0xff;
PORTA=0x00;//定义为无上拉电阻
}
voidInitADC()
{
ADMUX=0x40;//外部参考电压,右对齐,选择单通道ADC0
ADCSRA=0xe8;//AD使能,启动转换,及中断设置
SFIOR=0;//连续转换模式
}
voidmain()
{
InitPort();
InitADC();
while
(1);//等待ADC转换
}
voiddisp(intdisp_num)
{
ucharbai,ge,shi;
bai=disp_num/100;
shi=disp_num/100%10;
ge=disp_num%10;
PORTC=table[bai];
PORTB=smg_bit[0];
delay();
PORTC=table[shi];
PORTB=smg_bit[1];
delay();
PORTC=table[ge];
PORTB=smg_bit[2];
delay();
}
#pragmainterrupt_handleradc_isr:
15
voidadc_isr()
{
intadc_num;//存储ADC转换结果
ucharadc_l;
ucharadc_h;
adc_l=ADCL;
adc_h=ADCH;
adc_num=adc_h*256+adc_l;
disp(adc_num);
}
9.定时器普通模式
/*****************************************
定时器0,2是八位的,定时器1是16位
*1.根据需要选择时钟源(TCCR1B)
*2.设置时间初值(TCN1H,TCN1L)
*3.设置中断使能
*4.选择中断号,写中断服务程序
功能:
60s的定时器
****************************************/
#include
#include
#defineuintunsignedint
#defineucharunsignedchar
ucharnum;
uchartable[16]=
{0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
ucharsmg_bit[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
voiddelay()
{
uchari,j;
for(i=0;i<10;i++)
for(j=0;j<10;j++);
}
voidInitPort()
{
DDRB=0xff;//数码管输入模式
DDRA=0xff;
PORTB=0xff;
PORTA=0xff;
}
voidInitTimer1()
{
TCCR1B=0x04;//256分频
TCNT1H=0xf0;//Value=[65536-(选择的时钟频率)/(分频数)]->16进制
TCNT1L=0xc3;//这里的定时器是16位的定时器,不能当成两个八位的,这一点和51的不同
//时钟频率是“若干次周期每秒",分频之后,周期增大(AVR一个机器周期计数一次)
TIMSK|=BIT
(2);//中断使能位
SREG|=BIT(7);//总中断使能
}
voiddisp(intdisp_num)
{
ucharbai,ge,shi;
bai=disp_num/100;
shi=disp_num%100/10;
ge=disp_num%10;
PORTA=table[bai];
PORTB=smg_bit[0];
delay();
PORTA=table[shi];
PORTB=smg_bit[1];
delay();
PORTA=table[ge];
PORTB=smg_bit[2];
delay();
}
voidmain()
{
InitPort();
InitTimer1();
while
(1)
disp(num);//显示出来
}
#pragmainterrupt_handlertimer1_isr:
9
voidtimer1_isr()
{
TCNT1H=0xf0;//Value=[65536-(选择的时钟频率)/(分频数)]->16进制
TCNT1L=0xc3;
if(++num==60)
num=0;
}
10.定时器CTC模式(未测试)
/**********************************************
*1.如果输入波形,设置端口为输出(只有PD4,PD5可用于该模式的输出)
*2.设置波形发生模式和时钟源(TCCR1B)
*3.设置波形发生模式和引脚输出端口(TCCR1A)
*4.设置上限值(OCR1A)【这里是从0开始一直加到上限值】
*频率计算公式:
focn=fclk_IO/(2*N*OCR1A)这里的OCR1A就是上限值
focn就是想要输出波形的频率,N是分频数,flck_IO是晶振的频率,即每秒钟的时钟数
功能:
灯的亮度变化
**********************************************/
#include
#include
#defineucharunsignedchar
#defineuintunsignedint
voidInitTct()
{
DDRD=0x30;//将PD4,PD5都设置为输出波形的引脚
TCCR1B=0x09;//无分频(001)模式4:
WGM[13:
10]=(0100)
TCCR1A=0x50;
OCR1A=499;//这里是10进制数
}
voidmain()
{
InitTct();//不需要while
(1)的循环,因为该功能是独立于cpu执行的,只要设置之后会/自动产生
}//完
10.定时器PWM模式(未测试)
/******************************************
*1.设置端口输出
*2.设置PWM波形模式和选择时钟源(TCCR1A,TCCR1B)
*3.设置波形频率(OCR1A)【OC1A引脚控制周期】
*4.设置波形占空比(OCR1B)【OC1B引脚控制占空比】
*频率计算公式:
focn=fclk_IO/N*(1+TOP)[N=1,8,32,64,256,1024]
这里没有除以2
输出频率为200hz占空比为1/5的波形64分频
******************************************/
#include
#include
voidInitPwm()
{
DDRD=0x30;//OC1A,0C1B必须都输出
TCCR1A=0x63;
TCCR1B=0x1b;
OCR1A=77;
OCR1B=16;
}
voidmain()
{
InitPwm();//不行cup干预
}
11.UART通信(未测试成功)
/***********************************************
*1.初始化。
工作模式,帧结构等(UCSRC)[控制和状态寄存器C]
*2.波特率设置。
UBBRL,UBBRH
*3.中断相关设置。
UCSRB
*4.中断函数[打开总中断]
***********************************************/
#include
#include
#defineuintunsignedint
#defineucharunsignedchar
#definefosc1000000
ucharrdata;
ucharflag;
InitUart(uintbaud)
{
uchara;
UCSRC=0x86;//异步,禁止奇偶校验,一位停止位,八位字符长度
a=fosc/16/baud-1;//根据波特率计算总UBRR
UBRRL=a%256;
UBRRH=a/256;
UCSRB=0x98;
SREG|=BIT(7);//打开总中断
}
voidUartSend(uchardata)
{
while(!
(UCSRA&BIT(5)));
UDR=data;
while(!
(UCSRA&BIT(6)));
UCSRA|=BIT(6);
}
voidmain()
{
uchari='h';
InitUart(9600);
//UartSend(i);
while
(1)
{
if(flag)
{
flag=0;
UartSend(rdata);
}
}
}
#pragmainterrupt_handleruartrece_isr:
12
voiduartrece_isr()
{
rdata=UDR;
}