icn7211引脚功能

写这篇文章纯粹是想为博客拉點点击量。在博客园游客访问好像是不计入阅读量的,而作为一个十八线博主注册用户的访问应该以搜索引擎为主,博客园首页为次个位数的粉丝就别谈了。

所以希望各位从搜索引擎点进来的朋友,多多评论有问题咱们一起讨论。

我写过AVR单片机教程设计过自己嘚Arduino板,希望你相信我能给你带来收获

我不想听你放那么多屁,我只想知道周期为1ms的定时器中断怎么写!

在ATmega328P单片机中定时/计数器(Timer/Counter)是这样嘚组件:它需要一个时钟源,驱动一个8或16位的计数器递增或递减当计数器等于一个值时,会触发一些操作如产生中断、翻转引脚电平等。由于定时器的时钟源是系统时钟或外接晶振(一种产生频率精准的波的器件)分频得到的一旦设置好定时器的工作参数,直到下次调整參数定时器都会按照预期工作,与CPU执行的代码无关

之前有过这样的经历:跟一个优秀作品设计者聊了几句,他说同时控制舵机和扬声器很难控制好延时扬声器输出的音乐节奏会乱。我第一反应当然是他没有用定时器中断一问果然如此,并且他不知道中断也不知道定時器

还有一位同学,写TI计算器的程序在他的一个作品中,每次循环的计算量不定循环间隔也不定,导致游戏效果不好他的解决方法是根据计算量计算出循环最后需要的延时,使得循环间隔基本保持不变

这种思路是相当优秀的。但是如果有定时器可用的话编程难喥会降低,循环间隔的一致性也会更好是更加优秀的解决方案。

Arduino Uno Rev3的3、5、6、9、10、11号端口可以使用analogWrite和tone函数它们的功能都是利用定时器实现嘚。用函数确实方便但是只知使用而不知其原理就只能停留在技术的表面——Arduino的强大封装对开发者的学习有两面性。

定时器其实不知道什么3号端口它只知道OC2B。两种表示之间的对应关系如下表:端口编号硬件符号3PD3(PCINT19/OC2B/INT1)

寄存器是开发者与硬件打交道的方式从编程的语法上,可鉯把寄存器当作是变量可以对它赋值,也可以读取它的数值

寄存器中的位有几种不同的组织结构,它们的存取方式也不尽相同:

你也許一眼就能看出二进制的11在十进制中是3但是你很可能看不出23对应10111。在Arduino编程中(语言为C++)二进制数可以直接写,无需与十进制或十六进制转換Arduino提供的方法是B10111,GCC提供的是0b10111(0b前缀字面量是C++14标准才规定的)后者是我一直以来的习惯。

假如我要把这4个参数分别写为1、0、0b00、0b101就要写:

全昰0的可以不写,写是为了可读性ICNC1是寄存器的第7位,所以代码中它的值就是7其他位同理。

如果要判断ICNC1位是否为1:

有的位因为不存在而不能写如TCCR1B的第5位;有的位即使存在但是只读所以也不能写;有的位域分布于多个寄存器中,如WGM1[3:0]低两位在TCCR1A,高两位在TCCR1B

除了一个或多个位嘚位域以外,有些寄存器是整体使用的:

还有16位寄存器虽然读写不能用一句汇编搞定,但是高级语言层面上可以:

不超过255的话可以只写低字节TCNT1L

定时器相关寄存器总览:

读数据手册无疑是深入了解单片机的最好方法,可惜很多人没这个耐心几十页的英语也不是每个人都吃得消的。有些中文书打着介绍AVR单片机的幌子翻译数据手册不仅没有营养还漏洞百出,我不也推荐写这篇文章,也有避免后人重蹈覆轍的目的

当然,除了有代码示例以外本文再“详解”也详细不过数据手册,不过至少可以让你对定时器有个大致的印象不致于让你讀的时候一头雾水。

ATmega328P有3个定时器:定时器0、定时器1和定时器2(简单粗暴)0和2都是8位的,2支持异步工作;1是16位的精度更高,支持更多工作模式我接触过其他型号的单片机,AVR的定时器是相对简单的

定时器有3种工作模式:普通模式、CTC模式、PWM模式,其中PWM还分快速PWM、相位矫正(波形居中)PWM、相位与频率矫正PWM(频率可以任取仅限定时器1)。

先讲各种模式中共通的部分定时器需要一个时钟源,它可以是:时钟源适用范围无所有

T0(4)引脚上升/下降沿定时器0

T1(5)引脚上升/下降沿定时器1

工作模式之间的区别在于计数器的变化方向与范围介绍之前需要先下3个定义:名称描述BOTTOM0,计数器的最小值

MAX对8位定时器为0xFF对16位定时器为0xFFFF,计数器的最大可能值

TOP计数器达到这个值时可能会被清零,或变化方向改变

对定时器1可以为0x00FF、0x01FF、0x03FF、OCR1A或ICR1普通模式中,计数器从0开始增长到MAX然后溢出回到0,周而复始频率为(clkclk为定时器时钟频率)

CTC模式和快速PWM模式中,计数器从0開始增长到TOP然后不再继续增长而是直接回到0,重新开始增长频率为

两种相位矫正PWM模式中,计数器从0到TOP再从TOP回到0,如此循环频率为

當计数器的值与OCRnA或OCRnB相等时,可以对OCnx的电平进行一些操作所有模式下,OCnx都可以不连接定时器

非PWM模式下,可以把OCnx置为低电平、高电平或翻轉电平tone就是这样实现的;

PWM模式下,有正相和反相两种模式正相为OCRnx越大占空比越高,analogWrite就是这样实现的;反相反之;有些配置下OCnA可以被翻轉请参考数据手册。

由于引脚电平可以有宏观表现我们终于可以开始写代码了。

先试试tone在9号端口上连接一个蜂鸣器,使用定时器1的CTC模式产生440Hz方波:

OCR1A = 18181是怎么来的呢?每次计数器与OCR1A相等电平翻转两次为一周期,频率为clk2(OCR1A+1)clk2(OCR1A+1)先取clkclk为不分频试试,算出OCR1A为18181没有超过最大值65535,洇此就取这个如果超过了,就要把定时器频率下调直到OCRnx合理为止。

如果要让程序以频率为参数计算出合适的分频系数与OCRnx值可以参考tone嘚实现。

再试试analogWrite在3号端口上连接一个LED,使用定时器2的快速PWM模式实现呼吸灯的效果:

在快速PWM模式中,正相输出占空比不能为0反相输出占空比不能为1,如果要达到这两个值需要断开引脚与定时器的连接,用digitalWrite等方法输出

懒得写了,我抄我自己:中断是单片机的精华。

當一个事件发生时CPU会停止当前执行的代码,转而处理这个事件这就是一个中断。触发中断的事件成为中断源处理事件的函数称为中斷服务程序(ISR)。

中断在单片机开发中有着举足轻重的地位——没有中断很多功能就无法实现。比如在程序干别的事时接受UART总线上的输入,而uart_scan_char等函数只会接收调用该函数后的输入先前的则会被忽略。利用中断我们可以在每次接受到一个字节输入时把数据存放到缓冲区中,程序可以从缓冲区中读取已经接收的数据

AVR单片机支持多种中断,包括外部引脚中断、定时器中断、总线中断等每一个中断被触发时,通过中断向量表跳转到对应ISR如果一个中断对应的ISR不存在,链接器会把复位地址

}

我要回帖

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信