AVRmega16中断经典源程序
AVR mega16 简单的外中断C程序和相关寄存器解析
ISC11~ISC10:外部中断 1 的中断检测方式 ISC11 0 0 1 1 ISC01~ISC00:外部中断 0 的中断检测方式 ISC01 0 0 1 1 ISC00 0 1 0 1 表三 MCU 控制与状态寄存器-MCUCSR bit7 JTD bit6 ISC2 bit5 bit4 JTRF bit3 WDRF bit2 BORF bit1 EXTRF bit0 PORF INT0中断 低电平中断 INT1 引脚上任意的逻辑 电平变化都将引发中断 下降沿中断 上 ISC10 0 1 0 1 INT1中断 低电平中断 INT1 引脚上任意的逻辑电 平变化都将引发中断 下降沿中断 上升沿中断
個人說明:本文為本人學習的筆記,有不足之處請多多包涵,還請各路大俠多多指教。
INT1:使能外部中断请求1 INT0:使能外部中断请求0 INT2:使能外部中断请求 2 表五 通用中断标志寄存器 GIFR bit7 INTF1 bit6 INTF0 bit5 INTF2 bit4 bit3 bit2 bit1 IVSEL bit0 IVCE
INTF1:外部中断标志 INT1引脚电平发生跳变时触发中断请求,并置位相应的中断标志INTF1。如果SREG 的位I以及GICR寄存器相应的中断使能位INT1为”1”,MCU即跳转到相应的中断向量。 进入中断服务程序之后该标志自动清零。此外,标志位也可以通过写入”1” 来清零。
SE:MCU休眠使能位 SM1~SM0:MCU 休眠模式选择 SM2 0 0 0 0 1 1 1 1 SM1 0 0 1 1 0 0 1 1 SM0 0 1 0 1 0 1 0 1 休眠模式 空闲 ADC 噪声抑制模式 掉电模式 省电模式 保留 保留 Standby(1) 模式 扩展Standby(1) 模式
AVR的常用中断编程
实在没有财富了,才拿自己写的东西出来献丑。
平时自己并不常用A VR,所以没有写得很完全,这个是做参考用,如果您接纳了我这种写法,可以自己写完所有的东西自己建立一个固件库。
包含了三个文件,分别是interrupt.c、interruptt.h和MacroAndConst.h,如果有疑问或者见解可以发邮件给我,我的邮箱:349705262@。
现在粘贴如下:/*interrupt.h里面的内容*/#ifndef _INTERRUPT_H_#define _INTERRUPT_H_#include<iom16v.h>#include<macros.h>#include"MacroAndConst.h"#include"interrupt.h"extern void INT(uchar int_num,uchar sense_ctrl);/*函数名:exteral_int()(外部中断控制函数)参数:int_num(外部中断数),sense_ctrl(触发方式)外部中断的数int_num的取值为0和1,为0时是外部中断0,为1时是外部中断1sense_ctrl的取值如下:0:为低电平产生中断1:任意逻辑电平变化都产生中断2:下降沿产生中断3:上升沿产生中断功能:设置外部中断并使能外部中断函数编写流程:1、写MCU控制寄存器MCUCR,选择是外部中断0还是1,并且选择触发方式;2、写MCU控制与状态寄存器MCUCSR,选择使能外部中断。
调用例子:main(){INT(0,2);//设置外部中断0,下降沿触发中断SREG=0x80;//打开总中断while(1){}}#pragma interrupt_handler int0:2void int0()//外部中断0响应函数{//写执行语句}-----------------------------------------------------------------------------------*/extern void TCNT0_8bit(uchar timer_counter,uchar clock_select);/*函数名:TCNT0_8bit()(设置8位定时计数器为定时器)参数:timer_counter(定时计数器寄存器初始值),clock_select(时钟分频选择) clock_select可取一下值:0:无时钟,T/C 不工作1:1 分频( 没有预分频)2:8 分频( 来自预分频器)3:64 分频( 来自预分频器)4:256 分频( 来自预分频器)5:1024分频( 来自预分频器)6:时钟由T0 引脚输入,下降沿触发7:时钟由T0 引脚输入,上升沿触发功能:设置8位定时计数器并使能定时计数器函数编写流程:1、重置T/C控制寄存器,WGM0和WGM1为0,普通模式2、选择时钟源3、赋8位定时计数器初值4、溢出中断使能调用例子:void main(){TCNT0(142,5);//选择1024分频,初值为142SREG|=0x80;//打开总中断while(1){}}#pragma interrupt_handler int0:10void tcnt0(){TCNT0=142;//重新赋值//写需要执行的语句}-----------------------------------------------------------------------------------*/extern void TCNT1_16bit(uint tcnt1_val,uchar clock_select);/*函数名:TCNT1_16bit()(设置16为定时计数器为定时器)参数:tcnt1_val(TCNT1初始值),clock_select(时钟分频选择)clock_select可取一下值:0:无时钟,T/C 不工作1:1 分频( 没有预分频)2:8 分频( 来自预分频器)3:64 分频( 来自预分频器)4:256 分频( 来自预分频器)5:1024分频( 来自预分频器)6:时钟由T0 引脚输入,下降沿触发7:时钟由T0 引脚输入,上升沿触发功能:设置16位定时计数器并使能相应溢出中断函数编写流程:1、设置TCCR1A、TCCR1B寄存器2、选择时钟分频3、赋初始16位定时计数器值4、溢出中断使能调用例子:#pragma interrupt_handler tcnt0:9void main(){TCNT1_16bit(57722,5);SREG|=0x80;while(1){}}void tcnt0(){TCNT1=57722;//写相应语句}-----------------------------------------------------------------------------------*/extern void Input_Capture(void);/*------------------------------------------------------------------------------------------------*/extern void FAST_PWM_16bit(uchar clock_select,uint ICR1_val,uint OCR1A_val,uint OCR1B_val);/*函数名:FAST_PWM_16bit()(设置16位定时计数器的快速PWM功能)参数:clock_select(时钟分频选择),ICR1_val(ICR1寄存器的值),OCR1A_val(OCR1A寄存器的值),0CR1B_val(OCR1B寄存器的值)clock_select可取一下值:0:无时钟,T/C 不工作1:1 分频( 没有预分频)2:8 分频( 来自预分频器)3:64 分频( 来自预分频器)4:256 分频( 来自预分频器)5:1024分频( 来自预分频器)6:时钟由T0 引脚输入,下降沿触发7:时钟由T0 引脚输入,上升沿触发功能:设置16位定时计数器的快速PWM功能,快速PWM模式恒为14模式,此模式下TOP值恒设为ICR1寄存器中的值函数编写流程:1、设置PD4、PD5为输出2、设置TCCR1A、TCCR1B寄存器3、选择时钟分频4、赋值ICR1,OCR1A,OCR1B备注:PWM的频率可以计算如下:PWM频率=时钟频率/(分频数*(1+ICR1_val))PWM的占空比可计算如下:PWM占空比=OCR1A_val/ICR1 (PD5引脚输出)PWM占空比=OCR1B_val/ICR1 (PD4引脚输出)调用例子:void main(){FAST_PWM_16bit(3,1249,625,625);while(1){}}-----------------------------------------------------------------------------------*/#endif/*interrupt.c里面的内容*/#include"interrupt.h"void INT(uchar int_num,uchar sense_ctrl)//外部中断设置函数{switch(int_num){case 0: MCUCR|=sense_ctrl;//控制产生中断方式GICR|=0x40;//使能外部中断0break;case 1: MCUCR=MCUCR|(sense_ctrl*0x04);GICR|=0x80;break;case 2: MCUCSR=MCUCR||(sense_ctrl<<7);GICR=0x20;break;default:break;}}void TCNT0_8bit(uchar time_counter,uchar clock_select){TCCR0=0;//重置T/C控制寄存器,WGM0和WGM1为0,普通模式TCCR0|=clock_select;//选择时钟源TCNT0=time_counter;//初始化T/C寄存器TIMSK|=(1<<TOIE0);//溢出中断使能}void TCNT1_16bit(uint tcnt1_val,uchar clock_select){TCCR1A=0;//重置TCCR1ATCCR1B=0;//重置TCCR1B//普通模式TCCR1B|=clock_select;//选择时钟源TCNT1=tcnt1_val;//定时计数器初始化TIMSK|=(1<<TOIE1);//使能溢出中断}void Input_Capture(){TCCR1A=0;TCCR1B=0xc4;//使用输入噪声抑制器,输入捕捉为上升沿触发,时钟256分频TIMSK|=(1<<TICIE1);//输入捕捉中断使能TIMSK|=(1<<TOIE1);//T/C1溢出中断使能}void FAST_PWM_16bit(uchar clock_select,uint ICR1_val,uint OCR1A_val,uint OCR1B_val) {DDRD|=0x30;TCCR1A|=0XA2;//设置为快速PWM15模式,PD4、PD5口在匹配时输出电平翻转clock_select|=0x18;TCCR1B|=clock_select;ICR1=ICR1_val;OCR1A=OCR1A_val;OCR1B=OCR1B_val;}/*MacroAndConst.h里面的内容*/ #ifndef _MACRO_AND_CONST_H_ #define _MACRO_AND_CONST_H_typedef unsigned int uint;typedef unsigned char uchar; #endif。
atmege16外部中断程序
atmege16外部中断程序/****************************************** 功能:演示ATMEGA16的3个外部中断程序编辑环境:ICCAVR******************************************/#include<iom16v.h>#include<macros.h>#define uint unsigned int#define uchar unsigned char#define beep_0 (PORTD&=~(1<<PD7)) #define beep_1 (PORTD|=(1<<PD7))//蜂鸣器响uint count;/******************************************* 三个外部中断声明,注意中断向量号*******************************/#pragma interrupt_handler Exint0:2#pragma interrupt_handler Exint1:3#pragma interrupt_handler Exint2:19/*************************************系统延时函数************************************/void delay(uint ms){uint i,j;for(i=0;i<ms;i++){for(j=0;j<1140;j++);}}/**************************************端口初始化每个外部中断端口是固定的****************************************/void port_init(){DDRA=0XFF;PORTA=0XFF;DDRB&=(0<<PB2);//INT2PORTB|=(1<<PB2);DDRD&=(0<<PD2);//INT0PORTD|=(1<<PD2);DDRD&=(0<<PD3);//INT1PORTD|=(1<<PD3);}/***********************************外部中断初始化*******************************/void INT_init(){SREG=0X80;//打开全局中断GICR|=(1<<INT0)|(1<<INT1)|(1<<INT2);//三个中断使能MCUCR=(1<<ISC11)|(0<<ISC10)|(1<<ISC01)|(0<<ISC00);//I NT0,INT1下降沿触发MCUCSR=(0<<ISC2);//INT2下降沿触发中断}/***************************************** 流水灯函数****************************************/ void LED_1(){uchar i;for(i=0;i<8;i++){PORTA=~BIT(i);delay(200);}}/*********************************** LED_2函数**********************************/void LED_2(){PORTA=0X0F;delay(500);PORTA=0XF0;delay(500);}/********************************LED_3函数************************************/ void LED_3(){PORTA=0X81;delay(500);PORTA=0X7E;delay(500);}/************************************ 外中断0函数**********************************/ void Exint0(){LED_2();}/********************************** 外中断1函数***********************************/ void Exint1(){LED_3();}/************************外中断2函数***********************/void Exint2(){DDRD=(1<<PD7);for(count=0;count<4;count++) {beep_0;delay(200);beep_1;delay(200);}}/********************************* 主函数*********************************/ void main(){port_init();//端口初始化INT_init();//中断初始化while(1)// 当非0值时执行下面函数{LED_1();//流水灯函数}}。
第4章avrmega16单片机中断实例
• 4) 中断嵌套
在中断发生后,SREG的I位由硬件清除,并由 RETI(中断返回)指令置位,从而允许子序列的中断响应。
由于 AVR 在响应一个中断的过程中通过硬件将 I 标志 位自动清零,这样就阻止了 MCU响应其它中断。因此通 常情况下,AVR 是不能自动实现中断嵌套的。 如要系统中必须要实现中断嵌套的应用,用户可在中 断服务程序中使用指令将全局中断允许位开放,通过间接 的方式实现中断的嵌套处理。
1) MCU 控制寄存器—MCUCR
• MCU 控制寄存器 MCUCR 的低 4 位为 INT0(ISC01、 ISC00)和 INT1(ISC11、ISC10)中断触发类型控制位。
2)MCU 控制和状态寄存器—MCUCSR
• MCU 控制和状态寄存器 MCUCSR 中的第6位(ISC2) 为 INT2 的中断触发类型控制位。
void main(void) { PORTA=0xFF; DDRA=0xFF; PORTD|=0x0C; DDRD|=0x00; //DDRD.3=0;DDRD.2=0; GICR|=0xC0; MCUCR=0x0A; MCUCSR=0x00; GIFR=0xC0; //清除INT0、INT1中断标志位 #asm("sei") //SREG|=0x80; SREG.7=1; while (1) { PORTA=led_7[counter]; } }
4) 通用中断标志寄存器—GIFR
• 注意:用户可以使用指令将 INTFn 清除,清除的方式是 写逻辑“1”到 INTFn,将标志清零。另外, 当INT0 (INT1) 设置为低电平触发方式时, 标志位 INTF0 (INTF1) 始终为“0”,这并不意味着不产生中断请求, 而是低电平触发方式是不带中断标志类型的中断触发。在 低电平触发方式时,中断请求将一直保持到引脚上的低电 平消失为止。 • 而在开放中断允许前,一般应通过向 GIFR 寄存器中的中 断标志位 INTFn 写入逻辑“1” ,将该中断的中断标志位 清除,然后开放中断。这样可以防止在改变ISCn 的过程
ATMEGA16 中断GCC模式
AVR单片机中断实现ATmega16 INT ISR(INT0_vect)内容来源:本站发布时间:[2010-11-28]查看次数:42332.21 实例功能前面例子中分别介绍了按键控制发光二极管的亮灭,但是我们注意到,在程序中需要一直检测按键的状态,这样明显的浪费了单片机的资源,降低了单片机的工作效率,。
那么有没有一种方法可以让单片机不用一直检测按键的状态,而只在有按键动作时才去响应呢?当然有!单片机中除了具有基本输入输出功能的作用外,还有专门检测外界信号并作出响应的中断系统。
在本例中,通过利用外部中断实现单片机对按键事件的响应和处理。
本例中三个功能模块描述如下:● 单片机系统:对按键事件产生的中断时间作出响应,并在数码管上显示按键按下的次数。
● 外围电路:通过将按键连接到单片机的外部中断检测端口,实现中断产生电路,数码管显示电路用于指示按键的按下状态。
● 软件程序:编写AVR单片机的外部中断服务程序,从而实现对中断事件的响应。
2.2.2 器件和原理1单片机的中断系统关于中断的概念可以在一般的教材中找到,本例中只做简要叙述,不再详细说明。
中断属于一种对事件的实时处理过程。
中断源可能随时停止单片机当前正在处理的工作,转而去处理中断事件,待中断时间处理完毕之后,再返回原来工作的断点处,继续原来的工作。
对于单片机的中断系统,需要了解这几个概念:中断源、中断信号、中断向量、中断优先级、中断嵌套、中断控制(屏蔽)、中断响应条件、中断响应过程(中断服务程序)。
●中断源中断源是指能够向单片机发出中断请求信号的部件和设备。
对于单片机来讲,往往存在多个中断源。
中断源一般可分为内部中断源和外部中断源。
单片机内部集成的许多功能模块,如定时器、串行通讯口、模/数转换器等,它们在正常工作时往往无需CPU参与,而当处于某种状态或达到某个规定值需要程序控制时,会通过发出中断请求信号通知CPU。
这一类的中断源位于单片机内部,称作内部中断源。
mega16程序典例
#include <iom16v.h>#include <macros.h>/***************************函数申明*******************************************/void delay_1ms(void);//延时1毫秒void delay_nms(unsigned int);//延时n毫秒void white(void);//盲区循迹辅助函数void led(char);//一般循迹程序,输入行走格数void led1(char);//一般循迹程序,输入行走格数void led2(char);//后退循迹,输入行走格数void turnleft(void);//左转void turnright(void);//右转char mega_16ad(void);//ad转换函数void hold(void);//抓紧函数void lose(void);//放松函数void d_motor_s(unsigned char t);//小舵机控制函数void d_motor_b(unsigned char t);//大舵机控制函数void d_motor_r(unsigned char t);//大舵机恢复函数void motor (unsigned char m);//机械臂电机控制函数char catch(char);//抓取函数,包含ad转换函数,返回0未抓取,1黑色,2白色,3灰色//同时完成伸出机械臂,抓取,抬起机械臂动作void put(void);//伸出机械臂,放下棋子,抬起机械臂/********************************主函数****************************************/void main(void){char a,b,c=3;unsigned char i;DDRD|=BIT(4);DDRD|=BIT(5);TCCR1A=0XA2;TCCR1B=0X19;TCNT1=0X0000;ICR1=0x4A38;OCR1B=1054;delay_nms(50);OCR1A=2000;delay_nms(50);led1(2); //循迹,到达第一个棋子turnright();a=catch(1);//第一次抓取,记录棋子颜色turnleft();b=5;if(a==0) //若第一个为灰色,抓取下一个{led1(1);turnright();a=catch(1);turnleft();b=4;c=1;}led1(b); //到达指定位置,放下棋子if(a==1){turnright();put();turnright();}else {turnleft();put();turnleft();}led2(b-1);//后退b-1格turnleft();a=catch(2);//第二次抓取,记录棋子颜色turnleft();b=b-1;if(a==0) //若第二个为灰色,抓取第三个{led1(1);turnright();a=catch(2);turnleft();b=3;c=2;}led1(b);if(a==1){turnright();put();turnright();}else {turnleft();put();turnleft();}if(c==3)b=3;else if(c==2)b=4;else if(c==1)b=5;led2(b);//后退,取最后一个棋子turnleft();a=catch(3);turnleft();led1(b-1);{DDRD|=BIT(4);DDRD|=BIT(5);TCCR1A=0XA2;TCCR1B=0X19;TCNT1=0X0000;ICR1=0x4A38;OCR1B=2156;delay_nms(50);OCR1A=2000;delay_nms(50);for(i=0;i<18;i++){OCR1A+=100; delay_nms(20);OCR1B=2156;delay_nms(20);} OCR1B=2156;delay_nms(100);d_motor_s(2);delay_nms(1000);d_motor_s(1);}{DDRD|=BIT(4);DDRD|=BIT(5);TCCR1A=0XA2;TCCR1B=0X19;TCNT1=0X0000;ICR1=0x4A38;OCR1B=2156;delay_nms(50);OCR1A=3800;delay_nms(50);for(i=0;i<18;i++){OCR1A-=100; delay_nms(20);OCR1B=2156;delay_nms(20);} delay_nms(100);}led2(4);//往前走五格,放下灰色棋子put();turnleft();turnleft();led2(3);//后退四格,取车turnleft();catch(3);turnleft();led2(2);turnleft();//左转led2(1);put(); //放下车,将死turnright();//右转led1(2);//调用led2,往前走两格turnleft();led2(2);turnright();turnright();catch(3);turnleft();turnleft();//将举起,结束}/**************************** 时间延时函数************************************/ void delay_1ms(void){unsigned int i;for(i=0;i<150;i++){}}void delay_nms(unsigned int n){unsigned int i;for(i=0;i<n;i++)delay_1ms();}/************************ 循迹程序*********************************************/void led1(char num)// 向前循迹{char key,n=1;DDRA=0X3F;PORTA=0X35;delay_nms(500);PORTA=0X30;while(1){key=(PINB&0X2F);if(key<=0X0F){switch(key){case 0X06:PORTA=0X35;break;//旁路传感器5、6为白case 0X07:PORTA=0X35;break;case 0X0E:PORTA=0X35;break;case 0X0F:PORTA=0X35;break;case 0X00:white();break;case 0X03:PORTA=0X11;break;//左偏case 0X01:PORTA=0X11;break;case 0X02:PORTA=0X11;break;case 0X0C:PORTA=0X24;break;//右偏case 0X08:PORTA=0X24;break;case 0X04:PORTA=0X24;break;}}else if(key>=0X20){PORTA=0X30;delay_nms(10);key=(PINB&0X2F);if(key<=0X0F);else{if(n<num){while(1){key=(PINB&0X2F);if(key>0X0F)PORTA=0X35;else{n++;break;}}}else if(n==num){PORTA=0X30;delay_nms(20);break;}}}}}void led2(char num)// 向后循迹{char key,n=1;DDRA=0X3F;PORTA=0X35;delay_nms(500);PORTA=0X30;while(1){key=(PINB&0X1F);if(key<=0X0F){switch(key){case 0X06:PORTA=0X35;break;//旁路传感器5、6为白case 0X07:PORTA=0X35;break;case 0X0E:PORTA=0X35;break;case 0X0F:PORTA=0X35;break;case 0X00:white();break;case 0X03:PORTA=0X11;break;//左偏case 0X01:PORTA=0X11;break;case 0X02:PORTA=0X11;break;case 0X0C:PORTA=0X24;break;//右偏case 0X08:PORTA=0X24;break;case 0X04:PORTA=0X24;break;}}else{PORTA=0X30;delay_nms(10);key=(PINB&0X1F);if(key<=0X0F);else{if(n<num){while(1){key=(PINB&0X1F);if(key>0X0F)PORTA=0X35;else{n++;break;}}}else if(n==num){PORTA=0X30;delay_nms(20);break;}}}}}/*********************************循迹辅助*************************************/void white(void){unsigned char key;while(1){key=(PINB&0X0F);if(key==0X00){PORTA=0X24;delay_nms(1);PORTA=0X35;delay_nms(9);}else break;}}/*********************************转弯*****************************************/void turnleft(void)//左转{unsigned char key;DDRA=0X3F;PORTA=0X39;delay_nms(300);while(1){key=(PINB&0X0F);if(key==0X03){PORTA=0X30;delay_nms(20);break;}else PORTA=0X39;}}void turnright(void)//右转{unsigned char key;DDRA=0X3F;PORTA=0X36;delay_nms(300);while(1){key=(PINB&0X0F);if(key==0X0C){PORTA=0X30;delay_nms(20);break;}else PORTA=0X36;}}/*......................................AD转换................................*/char mega_16ad(void){int addata;DDRA&=~BIT(PA0);//PA口输入PORTA&=~BIT(PA0);ADMUX=0X27;//使用外部参考电压,右对齐,ADC0选择7通道ADCSR=0X80;//控制寄存器,adc使能,取消中断,2分频ADCSR|=BIT(6);// ADCR代表数字6,启动ADEwhile(!(ADCSR&(BIT(4))));//ADIF对应4,将第四位置位,其余为0 addata=ADCH;return addata;}char ad(void){int ad0;int ad1;char c;delay_nms(100); //延时500毫秒,稳定后采集信号while(1) //延时,两次相同采集信号{ad0=mega_16ad();delay_nms(10);ad1=mega_16ad();if(ad0==ad1)break;};if(ad0<0X033) c=2; //白线elseif((ad0>0X033)&&(ad0<0X75)) c=3; //灰线elseif(ad0>0x75) c=1; //黑线return c;}/*................................ 小舵机,PD4输出............................*/ void d_motor_s(unsigned char t){switch(t){case 2:{unsigned char i;DDRD|=BIT(4);TCCR1A=0X22;TCCR1B=0X19;TCNT1=0X0000;ICR1=0x2710;OCR1B=1500;for(i=0;i<5;i++)//松开{OCR1B-=111;delay_nms(10);}delay_nms(100);};break;case 1:{unsigned char i;DDRD|=BIT(4);TCCR1A=0X22;TCCR1B=0X19;TCNT1=0X0000;ICR1=0x2710;OCR1B=1500;for(i=0;i<6;i++)//加紧{OCR1B+=111;delay_nms(10);}delay_nms(100);};break;}}/*................... m为1放下传,为2抬升(110上,101下)......................*/ void motor (unsigned char m){unsigned char i;unsigned char j;DDRD|=BIT(5);TCCR1A=0X82;TCCR1B=0X19;TCNT1=0X0000;ICR1=0x4A38;//起点,确认居中if(m==2){OCR1A=3800;delay_nms(500);for(i=0;i<18;i++)//右转90度,缓慢{OCR1A-=100; delay_nms(40);}delay_nms(100);}else if(m==1){OCR1A=2000;delay_nms(500);for(i=0;i<18;i++)//右转90度,缓慢{ OCR1A+=100;delay_nms(40);}delay_nms(100);}}/*.................................抓取......................................*/char catch ( char a){char b,c;d_motor_s(2);motor(1);delay_nms(100);d_motor_s(1);delay_nms(100);b=ad();c=b;switch(a){case 1:{ if(b==1||b==2){unsigned char i;DDRD|=BIT(4);DDRD|=BIT(5);TCCR1A=0XA2;TCCR1B=0X19;TCNT1=0X0000;ICR1=0x4A38;OCR1B=2156;delay_nms(50);OCR1A=3800;delay_nms(50);for(i=0;i<18;i++)//右转90度,缓慢{OCR1A-=100; delay_nms(20);OCR1B=2156;delay_nms(20);}delay_nms(100);}else{d_motor_s(2);motor(2);delay_nms(100);c=0;}};break;case 2:{ if(b==1||b==2){unsigned char i;DDRD|=BIT(4);DDRD|=BIT(5);TCCR1A=0XA2;TCCR1B=0X19;TCNT1=0X0000;ICR1=0x4A38;OCR1B=2156;delay_nms(50);OCR1A=3800;delay_nms(50);for(i=0;i<18;i++)//右转90度,缓慢{OCR1A-=100; delay_nms(20);OCR1B=2156;delay_nms(20);}delay_nms(100);}else{d_motor_s(2);motor(2);delay_nms(100);c=0;}};break;case 3:{unsigned char i;DDRD|=BIT(4);DDRD|=BIT(5);TCCR1A=0XA2;TCCR1B=0X19;TCNT1=0X0000;ICR1=0x4A38;OCR1B=2156;delay_nms(50);OCR1A=3800;delay_nms(50);for(i=0;i<18;i++){OCR1A-=100; delay_nms(20);OCR1B=2156;delay_nms(20);}delay_nms(100);c=3;};break;};return c;}/*.....................................放下...................................*/void put ( void){unsigned char i;DDRD|=BIT(4);DDRD|=BIT(5);TCCR1A=0XA2;TCCR1B=0X19;TCNT1=0X0000;ICR1=0x4A38;OCR1B=2156;delay_nms(50);OCR1A=2000;delay_nms(50);for(i=0;i<18;i++){OCR1A+=100; delay_nms(20);OCR1B=2156;delay_nms(20);}OCR1B=2156;delay_nms(100);d_motor_s(2);motor(2);delay_nms(100);}。
ATmega16中断
▪ 每一个外部中断源都有相应的中断标志位; ▪ 某一个外部中断源申请中断,相应中断标志位置1。
中断源
INT0 INT1 INT2
中断标志位
INTF0 INTF1 INTF2
中断标志位由 CPU自动置“1” 当CPU响应中断 后,则中断标志 位自动 清“0”; 也可以通过对其 写“1”来清“0”
数字 y
xunce_7219(char i,int y,char n) —— 显示函数
数字编号,显示 器的1~2位显示i
显示的数字,显示n器为小数点的 的3~8位显示y 位置
实 验 结 果 仿 真
(PB4)/SS (PB7)SCK
(PB5)MOSI
MAX 7219
8位LED显1示0234567891器
中断源的中断请求将被响应。 位4~0:与外部中断的设置无关。
在ICCAVR C开发系统中,可通过编程向导对位
7~5进行设置。
MCU控制寄存器 —— MCUCR
7654 3 210
SM2 SE SM1 SM0 ISC11 ISC10 ISC01 ISC00
位3~0:外部中断1、 0中断请求信号有效方式控制位。
清 志“ 位总 价显0#中”a示I断sN芯m开T(片F“放0可s初标,e由自始i等”编动化) 程生向 成导
等待初始化完成
delay_ms(20);//
输出方波,作为外
while (1)
部延中时断,请改求变信此号值即改变
{
方波的频率,也即改变
PORTC.2=!PORTC.2;// 中断请求的频率
delay_ms(500);//
4.ATmega16中断系统
编 译 开 关
关键字
Байду номын сангаас
自定义 函数名
函数名
中断源中断服务 程序主体
四、中断系统 6、中断应用编程
编程步骤: (1)确定中断源(内部中断,外部中断) (2)如是INT中断还得设定外部中断触发方式 MCUCR——INT0,INT1; MCUCSR——INT2; (3)开放可屏蔽中断源(打开中断开关) SREG.7——中断总开关; GICR ——中断源开关 (4)编写中断事件函数
四、中断系统 4、外部中断
INT0、INT1和INT2 3个外部中断源,分别由芯片外部引 脚PD2、PD3、PB2上的电平的变化或状态作为中断触发信号。 其中,INT0和INT1支持4种中断触发方式,INT2支持2种。
四、中断系统 4、外部中断
特 点: ●低电平触发是不带中断标志类型的,只要PD2或PD3保持低 电平,一直会产生中断申请。������ ● MCU对INT0和INT1的引脚上的上升沿或下降沿变化的识别 (触发),需要I/O时钟信号的存在(由I/O时钟同步检测 ),属于同步边沿触发的中断类型。������ ● MCU对INT2的引脚上的上升沿或下降沿变化的识别(触发 ),以及低电平的识别(触发)是通过异步方式检测的, 不需要I/O时钟信号。因此,这类触发类型的中断经常作为 外部唤醒源。������
四、中断系统 5、中断寄存器
在ATmega16中,除了寄存器SREG中的全局中断允许标 志位I外,与外部中断有关的寄存器有4个,共有11个标 志位。其作用分别是: ●3个外部中断中断标志位, ● 3个中断允许控制位 ● 用于定义外部中断的触发类型。
(1)中断控制寄存器——MCUCR
四、中断系统 5、中断寄存器
ATmega16定时器中断
ATmega16定时器/计数器中断及编程Atmega16内部有三个定时器/计数器T/C0,T /C1.T/C2,其中T/C0,T/C2为8为定时器,T/C1为16定时器,这里从高级语言编程的使用出发,简要介绍T/C0的使用。
定时器中断的过程是:当中断发生时,程序控制立即从主程序转移到中断服务程序,执行完中断服务程序后再返回到主程序的中断处继续执行后续的程序。
利用中断可以节省CPU资源。
先了解几个寄存器。
MCUCR---MCU控制寄存器;MCUCSR-----MCU控制与状态寄存器;GICR-----通用控制寄存器;GIFR-----通用中断标志寄存器;TIFR---定时器中断标志寄存器,TIMSK----定时器中断屏蔽寄存器。
这几寄存器保留默认设置即可,需要编程时了解并设置的寄存器为TCCR0----T/C0控制寄存器,TCNT0----T/C0的计数初始值,OCR0----输出比较寄存器,OC0/PB3----输出比较引脚。
TCCR0为8位寄存器,从高位到低位的名称依次是:FOC0,WGM00,COM01,COM00,WGM01,CS02,CS01,CS00.TCCR0各个控制位的作用:(1) CS02,CS01,CS00控制时钟选择和预分频,如100表示预分频为256(2) WGM01,WGM00控制波形产生模式,分为普通模式(用于普通计时),CTC模式(用于频率发生),快速PWM模式(用于PWM调速,功率调节),相位修正PWM模式。
如10表示CTC模式。
(3) COM01,COM00控制比较匹配输出模式。
在不同的波形产生模式下其逻辑值功能表不同,如在普通模式或CTC模式下01表示比较匹配发生OC0取反。
(4)FOC0,中断标志位,设为零即可。
至于上述控制位的逻辑值功能表可查阅Atmega16的中文数据手册,在官方网上会有英文版。
完成TCCR0的设定,接下来是设置TCNT0,OCR0寄存器了。
AVR笔记:外部中断
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,此时程序会自动转到中断程序子函数。
然后有硬件自动清零,以等待下一次的中断发生。
个人总结的AVR的ATMEGA16L单片机程序
ATMAGE 16 的C语言程序ATMAGE 16 的C语言程序 (1)一、PB0 口的PB0.1 LED 发光管闪烁的程序: (3)二、PA0、PB0、PC0口的LED 发光管闪烁的程序: (5)三、I/O口的输入与输出 (6)四、跑马灯 (8)五、数码管计数显示设计 (10)六、控制直流电机正反转 (16)七、单片机的定时器(T/C0)应用 (20)AVR原理图 (24)一、PB0 口的PB0.1 LED 发光管闪烁的程序:#include <avr/io.h>int main( void ){unsigned char i, j, k,led=0;DDRB=0xFF; /* all outputs */while (1){if(led)PORTB|=0X01; /* |使最后一位为1 */elsePORTB&=0XFE; /*&最后一位为0 */ led=!led;//延时for (i=0; i<255; i++)for(j=0; j<255;j++)k++;}}/////////////////////////////////////////////////////////////// #include <avr/io.h>int main( void ){unsigned char i, j, k,led=0;DDRB=0xFF; /* all outputs */while (1){if(led)PORTB=0Xfe;elsePORTB=0Xff;led=!led;for (i=0; i<255; i++) //延时for(j=0; j<255;j++)k++;}}二、PA0、PB0、PC0口的LED 发光管闪烁的程序:#include <avr/io.h>int main( void ){unsigned char i, j, k,led=0;DDRA=0xFF;//为输出DDRB=0xFF;DDRC=0XFF;while (1){if(led){PORTA|=0XFF;PORTB|=0XFF;PORTC|=0XFF;}else{PORTA&=0X00;PORTB&=0X00;PORTC&=0X00;}led=!led;//取反////////////延时////////////////for (i=0; i<255; i++)for(j=0; j<255;j++)k++;}}三、I/O口的输入与输出#include <avr/io.h>///////////////////延时us//////////////////void delay_us(int t){dot--;while(t>1);}///////////////////延时ms///////////////// void delay_ms(unsigned int t){while(t!=0){delay_us(1142);t--;}}///////////////////主程序/////////////////////int main(void){DDRA = 0xff; /* all outputs */ DDRB = 0xff; /* all outputs */ DDRC = 0xff; /* all outputs */PORTA=0XFF;PORTB=0XFF;PORTC=0XFF;while(1){//***IO口输出低电平有效,如:0X01为十六进制数,二进制表示为00000001B,再取反////////A口输出//////PORTA=~0X01; // ~表示取反delay_ms(100);//延时N秒PORTA=~0X02;delay_ms(100);PORTA=~0X04;delay_ms(100);PORTA=~0X08;delay_ms(100);PORTA=~0X10;delay_ms(100);PORTA=~0X20;delay_ms(100);PORTA=~0X40;delay_ms(100);PORTA=~0X80;delay_ms(100);PORTA=0X00;//循环结束全亮////////B口输出//////PORTB=~0X01;delay_ms(100);PORTB=~0X02;delay_ms(100);PORTB=~0X04;delay_ms(100);PORTB=~0X08;delay_ms(100);PORTB=~0X10;delay_ms(100);PORTB=~0X20;delay_ms(100);PORTB=~0X40;delay_ms(100);PORTB=~0X80;delay_ms(100);PORTB=0X00;////////C口输出//////PORTC=~0X01;delay_ms(100);PORTC=~0X02;delay_ms(100);PORTC=~0X04;delay_ms(100);PORTC=~0X08;delay_ms(100);PORTC=~0X10;delay_ms(100);PORTC=~0X20;delay_ms(100);PORTC=~0X40;delay_ms(100);PORTC=~0X80;delay_ms(100);PORTC=0X00;}}四、跑马灯#include <avr/io.h>#define uchar unsigned char#define uint unsigned intvoid delayms(uint i){uint j;for(;i!=0;i--){for(j=8000;j!=0;j--);}}void horse(uchar i){switch (i){case 1:PORTB=0X01;break; case 2:PORTB=0X03;break; case 3:PORTB=0X07;break; case 4:PORTB=0X0f;break; case 5:PORTB=0X1f;break;case 6:PORTB=0X3f;break; case 7:PORTB=0X7f;break; case 8:PORTB=0Xff;break; default:break;}}void main(void){uchar i;DDRB=0XFF;PORTB=0XFF;PORTB=0X00;delayms(10);while(1){for(i=1;i<9;i++){horse(i);delayms(10);}for(i=7;i!=0;i--){horse(i);delayms(10);}}五、数码管计数显示设计1、两个按键PB0和PB1分别控制加减。
AVR ATmega16 EEPROM读写程序源码
void delay(uint ms) //延迟函数 { uint i,j; for (i=0;i<ms;i++) for (j=0;j<1141;j++); } /********************************************************** LCD1602相关定义 **********************************************************/ void wr_com(uchar com) //写命令函数 { CTRL_PORT &=~BIT(0); CTRL_PORT &=~BIT(1); DATA_PORT =com; CTRL_PORT &=~BIT(2); delay(1); CTRL_PORT |=BIT(2); delay(1); } void wr_data(uchar data) { //写数据函数 //RS置0 //RW置1 //E置0 //E置1,产生上升沿,开始写入
第7页 共 9页
AVR ATmega16 EEPROM 读写程序
CTRL_PORT |=BIT(0); CTRL_PORT &=~BIT(1); DATA_PORT = data; CTRL_PORT &=~BIT(2); delay(1); CTRL_PORT |=BIT(2); delay(1); }
(3) EEPROM 控制寄存器- EECR
Bit
读/写 初始值
7
-
6
-
5
-
4
-
3
EERIE
2
EEMWE
1
EEWE
0
AVRmega16中断经典源程序
AVRmega16中断经典源程序AVRmega16中断经典源程序,内含完整各中断的使用,真正做到一通百通,avrmega16中断轻松上手#include<iom16v.h>#include<macros.h>#define uchar unsigned char#define uint unsigned intvoid delay(void){uint a,b;for(a=0;a<10;a++)for (b=0;b<500;b++);}void init (){DDRB|=BIT(0);//端口初始化PORTB=BIT(0);//端口初始化DDRA|=0xff; //端口初始化PORTA=0xff; //端口初始化,要想用到那个端口,就必须先初始化MCUCR|=0x02;//0000 0000 INT0低电平产生外部中断请求//0000 0001 INT0任意逻辑电平都将引发产生外部中断请求//0000 0010 INT0下降沿产生外部中断请求//0000 0011 INT0上升沿产生外部中断请求GICR|=BIT(6);//对第六位置1;BIT7-INT1 // BIT6-INT0// BIT5-INT2DDRD&=~BIT(2);//PD2置0PORTD|=BIT(2);//PD2置1 带上拉电阻的输入//DDRxn PORTxn I0 上拉电阻说明// 0 0 输入无高阻态// 0 1 输入有带上拉的输入// 1 0 输出无输出低电平// 1 1 输出无输出高电平SREG|=BIT(7); //开全局中断}/*主函数写闪烁灯*/void main(void){init();while(1){PORTB|=BIT(0);delay();PORTB &=~BIT(0);delay();}}#pragma interrupt_handler int0_isr:2 void int0_isr(void){PORTA=0;delay(); PORTA=0xff;}。
AVR Mega16中断与定时器
中断与定时器AVR Mega16 一共有21个中断源 3个外部中断 INT0、INT1、INT2 8个定时器中断3个串口中断 RXC 、TXC 、UDRESPI 、AD 、EEPROM 、模拟比较、TWI 、SPM 各一个 RESET 中断 SPI 串行传输结束SPI, STC$01411保存程序存储器内容就绪SPM_RDY$02821定时器/ 计数器0 溢出TIMER0 OVF $012 10定时器/ 计数器0 比较匹配TIMER0 COMP $026 20定时器/ 计数器1 溢出TIMER1 OVF $010 9外部中断请求2INT2 $024 19定时器/ 计数器1 比较匹配B TIMER1 COMPB $00E 8两线串行接口TWI$02218定时器/ 计数器1 比较匹配 ATIMER1 COMPA $00C7模拟比较器ANA_COMP $020 17定时器/ 计数器1 事件捕捉TIMER1 CAPT $00A 6EEPROM 就绪EE_RDY $01E 16定时器/ 计数器2 溢出TIMER2 OVF $008 5ADC 转换结束ADC $01C 15定时器/ 计数器2 比较匹配TIMER2 COMP $006 4USART , Tx 结束USART, TXC$01A 14外部中断请求1INT1 $004 3USART 数据寄存器空USART, UDRE $018 13外部中断请求0INT0 $002 2USART , Rx 结束USART, RXC $01612外部引脚电平引发的复位,上电复位,掉电检测复位,看门狗复位,以及JTAG AVR 复位RESET$0001中断定义中断源程序地址向量号中断定义中断源程序地址向量号MCU 控制寄存器— INT0、INT1INTx 的上升沿产生异步中断请求11INTx 的下降沿产生异步中断请求0 1 INTx 引脚上任意的逻辑电平变化都将引发中断1 0 INTx 为低电平时产生中断请求0 0 说明ISCx0 ISCx1MCU 控制与状态寄存器—INT2INT2上升沿产生中断请求1INT2下降沿产生中断请求0 说明ISC2外部中断控制——通用中断控制寄存器GICRGICR 的INTx置位为允许INTx 中断 GICR 的INTx 清零为禁止INTx 中断通用中断标志寄存器-GIFR外部中断产生时,硬件自动置位对应的中断请求标志位 中断响应时,硬件自动清除中断请求标志位 中断请求标志位可以通过软件写“1”实现清零 T/C0控制寄存器TCCR0普通模式和CTC模式下:定时器中断屏蔽寄存器-TIMSKOCIE2(OCIE0): T/C2(T/C1)输出比较匹配中断允许标志位OUTPUT COMPARE INTERRUPT ENABLE TOIE2(TOIE0): T/C2(T/C1)溢出中断允许标志位OC0引脚方波频率:CTC模式下利用比较匹配产生波形输出)1(2/_OCRnNff OICLKOCn+=T0计数寄存器-TCNT0T0比较输出寄存器-OCR0定时器中断标志寄存器-TIFR特殊功能IO 寄存器-SFIPSR10: T/C1 与T/C0 预分频器复位T/C1 与T/C0 共用同一预分频器,且预分频器复位对两个定时器均有影响。
AVR教程系列一(12):ATmega16 简介(六)
A VR教程系列一(12):ATmega16 简介(六) ATmega16 操纵与状态寄存器MCUCSRAVR 操纵与状态寄存器提供了有关引起AVR复位的复位源的信息。
Bit 4 – JTRF: JTAG 复位标志通过JTAG 指令AVR_RESET 能够使JTAG 复位寄存器置位,并引发MCU 复位,并使JTRF 置位。
上电复位将使其清零,也能够通过写”0” 来清除。
Bit 3 – WDRF: 看门狗复位标志看门狗复位发生时置位。
上电复位将使其清零,也能够通过写”0” 来清除。
Bit 2 – BORF: 掉电检测复位标志掉电检测复位发生时置位。
上电复位将使其清零,也能够通过写”0” 来清除。
Bit 1 – EXTRF: 外部复位标志外部复位发生时置位。
上电复位将使其清零,也能够通过写”0” 来清除。
Bit 0 – PORF: 上电复位标志上电复位发生时置位。
只能通过写”0” 来清除。
为了使用这些复位标志来识别复位条件,用户应该尽早读取此寄存器的数据,然后将其复位。
假如在其他复位发生之前将此寄存器复位,则后续复位源能够通过检查复位标志来熟悉。
ATmega16 基准电压使能信号与启动时间ATmega16 具有片内能隙基准源,用于掉电检测,或者者是作为模拟比较器或者ADC的输入。
ADC 的2.56V 基准电压由此片内能隙基准源产生。
电压基准的启动时间可能影响其工作方式。
启动时间列于Table 16。
为了降低功耗,能够操纵基准源仅在如下情况打开:1. BOD 使能 ( 熔丝位BODEN 被编程)2. 能隙基准源连接到模拟比较器(ACSR 寄存器的ACBG 置位)3. ADC 使能因此,当BOD 被禁止时,置位ACBG 或者使能ADC 后要启动基准源。
为了降低掉电模式的功耗,用户能够禁止上述三种条件,并在进入掉电模式之前关闭基准源。
ATmega16 看门狗定时器看门狗定时器由独立的1 Mhz 片内振荡器驱动。
IAR_AVR_C语言中断编程
四、MCU 控制与状态寄存器-MCUCSR
第 2 页 共 5 页
7 JTD 初始值 0
6 ISC2 0
5 0
4 JTRF
3 WDRF
2 BORF
1 EXTRF
0 PORF
Bit 6 – ISC2: 中断 2 触发方式控制 异步外中断 2 由外部引脚 INT2 激活,如果 SREG 寄存器的 I 标志和 GICR 寄存器相应的 中断屏蔽位置位的话。若 ISC2 写 0, INT2 的下降沿激活中断。 若 ISC2 写 1,INT2 的 上升沿激活中断。 INT2 的边沿触发方式是异步的。只要 INT2 引脚上产生宽度大于 50nS 的 脉冲就会引发中断。若选择了低电平中断,低电平必须保持到当前指令完成,然后才会产生 中断。而且只要将引脚拉低,就会引发中断请求。改变 ISC2 时有可能发生中断。因此建议 首先在寄存器 GICR 里清除相应的中断使能位 INT2,然后再改变 ISC2。最后,不要忘记在 重新使能中断之前通过对 GIFR 寄存器的相应中断标志位 INTF2 写 '1’使其清零。 五、通用中断控制寄存器-GICR 7 INT1 初始值 0 6 INT0 0 5 INT2 0 4 0 3 0 2 0 1 IVSEL 0 0 IVCE 0
IAR AVR 中的定义 RESET_vect INT0_vect INT1_vect TIMER2_COMP_vect TIMER2_OVF_vect TIMER_ CAPT_vect TIMER1_COMPA_vect TIMER1_COMPB_vect TIMER1_OVF_vect TIMER0_OVF_vect SPI_STC_vect USART_RXC_vect USART_UDRE_vect USART_TXC_vect ADC_vect EE_RDY_vect ANA_COMP_vect TWI_vect INT2_vect TIMER0_COMP_vect SPM_RDY_vect
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
}
/*主函数写闪烁灯*/
void main(void)
{
init();
while(1)
{
PORTB|=BIT(0);
delay();
PORTB &=~BIT(0);
delay();
}
}
#pragma interrupt_handler int0_isr:2
#include<iom16v.h>
#include<macros.h>
#define uchar unsigned char
#define uint unsigned int
void delay(void)
{
uint a,b;
for(a=0;a<10;a++)
for (b=0;b<500;b++);
// 0 0 输入 无 高阻态
// 0 1 输入 有 带上拉的输入
// 1 0 输出 无 输出低电平
// 1 1 输出 无 输出高电平
void int0_isr(void)
{
PORTA=0;
delay();
PORTA=0xff;
}
}
void init ()
{
DDRB|=BIT(0);//端口初始化
PORTB=BIT(0);//端口初始化
DDRA|=0xff; //端口初始化
PORTA=0xff; //端口初始化,要想用到那个0000 0000 INT0低电平产生外部中断请求
//0000 0001 INT0任意逻辑电平都将引发产生外部中断请求
//0000 0010 INT0下降沿产生外部中断请求
//0000 0011 INT0上升沿产生外部中断请求
GICR|=BIT(6);//对第六位置1;BIT7-INT1
// BIT6-INT0
// BIT5-INT2
DDRD&=~BIT(2);//PD2置0
PORTD|=BIT(2);//PD2置1 带上拉电阻的输入
//DDRxn PORTxn I0 上拉电阻 说明