AVR.docx

上传人:b****4 文档编号:2966873 上传时间:2022-11-16 格式:DOCX 页数:13 大小:23.46KB
下载 相关 举报
AVR.docx_第1页
第1页 / 共13页
AVR.docx_第2页
第2页 / 共13页
AVR.docx_第3页
第3页 / 共13页
AVR.docx_第4页
第4页 / 共13页
AVR.docx_第5页
第5页 / 共13页
点击查看更多>>
下载资源
资源描述

AVR.docx

《AVR.docx》由会员分享,可在线阅读,更多相关《AVR.docx(13页珍藏版)》请在冰豆网上搜索。

AVR.docx

AVR

AVR单片机寄存器介绍

数据寄存器(UDR),UDR实际上是两个寄存器,USART的接收数据缓冲器和发送数据缓冲器,他们共用一个地址,因而共用一个名字。

由于接受数据缓冲器是只读的,程序中的读UDR操作被自动寻址到接收数据缓冲器;而写操作被自动寻址到发送数据缓冲器,这样就保证了两个数据缓冲器虽用同一个名字但并不会被混淆。

USART控制与状态寄存器A(UCSRA)是个8位寄存器,每一位的定义如下:

RXCTXCUDREFEDORPEU2XMPCM

76543210

位7—RXC:

USART接收完成。

当USART接收完一个字符,并且这个字符还没有被读取时,该位自动变为1。

该位对于串口通信编程的意义在于我们可以在程序中查询它的值,如果为1,则可以知道USART已经接收完一个字符,接下来的程序就可以去相应的位置(寄存器UDR,此时为只读接收缓冲器)去读取这个字符,RXC在这个过程中被自动清0;如果为0,就等待,直至RXC变为1。

位6—TXC:

USART发送完成。

当USART发送完一个字符,并且没有新的字符需要发送,该位变为1。

该位为1说明此时USART可以发送新的字符。

如果在程序中需要向外部接收器发送一组字符(将待发送字符写入寄存器UDR,写操作自动选择发送缓冲器),可以查询该位;为1,可以发送下一个字符,为0,等待直至该位变为1。

位5—UDRE:

USART数据寄存器空。

USART发送字符时,当写入UDR的字符被送到发送移位寄存器中向外传输时,该位变为1。

该标志位意味着UDR中可以写入新的待发送数据。

UDRE与TXC的相同之处在于他们的值为1时都可以向UDR中写入新的待发送数据;不同之处在于,TXC表征的意义在于发送字符操作完成,不仅说明UDR中的字符被送到发送移位寄存器(即UDRE所表征的意义),而且也完成了从发送移位寄存器向外部的传输。

位4—FE:

接收帧出错。

如果在接收缓冲器中刚接收到的数据被检测到帧出错,该位变为1。

位3—DOR:

接收数据溢出出错。

如果接收数据溢出条件被检测到,该位变为1。

位2—PE:

校验错误:

接收器检测到刚接收的数据校验出错,该位变为1。

如果使用该功能,首先需要设置校验位允许使用,在寄存器UCSRC中介绍。

位1—U2X:

USART传输速率倍速。

该位只有在异步模式下有效,它的功能是使通信的传输速度加倍。

位0—MPCM:

多机通信模式允许。

USART控制与状态寄存器B(UCSRB)的定义如下:

RXCIETXCIEUDRIERXENTXENUCSZ2RXB8TXB8

76543210

位7—RXCIE:

USART接收完成中断允许。

如果该位被设置为1,表示允许响应接收完成中断请求。

如果全局中断标志I为1,且RXCIE也为1,则当UCSRA中的RXC为1,即USART接收完成,将产生一个中断请求,CPU会保护现场后去执行相应的中断服务程序。

中断就是CPU放下目前正在处理的任务,转而处理引起中断的事务。

ATmega16的中断系统将在以后的篇章中介绍,本篇中的串口通信程序采用查询标志位的方法,不使用中断。

位6—TXCIE:

USART发送完成中断允许。

如果该位被设置为1,表示允许响应发送完成中断请求。

同RXCIE。

位5—UDRIE:

USART数据寄存器空中断允许。

当该位被设置为1时,表示允许响应发送数据寄存器UDR空中断请求。

同RXCIE。

位4—RXEN:

USART接收数据允许。

当该位被设置为1时,允许USART接收数据。

也就是说如果你准备用串口接收数据,那么首先需要将此位设置为1。

此时管脚PD0(RXD)由通用I/O口转变为第二功能RXD。

位3—TXEN:

USART发送数据允许。

当该位被设置为1时,允许USART发送数据。

位2—UCSZ2:

USART数据位设定。

该位协同UCSRC寄存器中的UCSZ1,UCSZ0位设定通信字符的位长(5,6,7,8,9位)。

UCSZ2UCSZ1UCSZ0字符长度

0005

0016

0107

0118

100保留

101保留

110保留

1119

位1—RXB8:

接收字符的第8位。

当设定的通信字符位长为9时,该位用来表示接收数据的最高位,即第8位。

位0—TXB8:

发送字符的第8位。

同RXB8。

USART控制与状态寄存器C(USARTC)的定义如下:

URSELUMSELUPM1UPM0USBSUCSZ1UCSZ0UCPOL

76543210

位7—URSEL:

寄存器选择。

该位用于选择要操作的寄存器是UCSRC或者是UBRRH。

读取UCSRC时,该位读出值为1;写UCSRC寄存器时,必须将该位写入1才能够正常写入UCSRC寄存器。

UPM1UPM0校验方式

00无校验

01保留

10偶校验

11奇校验

位6—UMSEL:

工作状态选择。

该位为写入0时为异步模式;写入1为同步模式。

位5,位4—校验方式选择。

选择串行数据通信采用何种校验

方式。

如表格所示。

位3—USBS:

停止位选择。

为0时,数据帧中包含1位停止位;为1时,数据帧中包含2位停止位。

位0—UCPOL:

时钟极性选择。

该位只在同步模式下使用。

在异步通信模式中应将此位写0。

波特率寄存器(UBRRH,UBRRL):

UBRRL与UBRRH的低4位构成一个12位寄存器,用来设置串行通信的速率。

需要注意一点的是在写UBRRH寄存器时,最高位(第7位)必须写入0。

来看一下波特率如何计算。

其中,BARR即所需要求得的UBRR寄存器的值;fosc为晶体频率;BAUD即通信波特率。

比如准备以9600的波特率进行通信,晶体为14.7456MHZ,可得到BARR=95。

当然,波特率也可以通过查表来获得。

2.C语言高效编程的几招

第1招:

以空间换时间

  计算机程序中最大的矛盾是空间和时间的矛盾,那么,从这个角度出发逆向思维来考虑程序的效率问题,我们就有了解决问题的第1招——以空间换时间。

  例如:

字符串的赋值。

  方法A,通常的办法:

  #defineLEN32

  charstring1[LEN];

  memset(string1,0,LEN);

  strcpy(string1,“Thisisaexample!

!

”);

  方法B:

  constcharstring2[LEN]=“Thisisaexample!

”;

  char*cp;

  cp=string2;

  (使用的时候可以直接用指针来操作。

  从上面的例子可以看出,A和B的效率是不能比的。

在同样的存储空间下,B直接使用指针就可以操作了,而A需要调用两个字符函数才能完成。

B的缺点在于灵活性没有A好。

在需要频繁更改一个字符串内容的时候,A具有更好的灵活性;如果采用方法B,则需要预存许多字符串,虽然占用了大量的内存,但是获得了程序执行的高效率。

  如果系统的实时性要求很高,内存还有一些,那我推荐你使用该招数。

  该招数的变招——使用宏函数而不是函数。

举例如下:

  方法C:

  #definebwMCDR2_ADDRESS4

  #definebsMCDR2_ADDRESS17

  intBIT_MASK(int__bf)

  {

    return((1U<<(bw##__bf))-1)<<(bs##__bf);

  }

  voidSET_BITS(int__dst,int__bf,int__val)

  {

    __dst=((__dst)&~(BIT_MASK(__bf)))|\

      (((__val)<<(bs##__bf))&(BIT_MASK(__bf))))

  }

  SET_BITS(MCDR2,MCDR2_ADDRESS,RegisterNumber);

  方法D:

  #definebwMCDR2_ADDRESS4

  #definebsMCDR2_ADDRESS17

  #definebmMCDR2_ADDRESSBIT_MASK(MCDR2_ADDRESS)

  #defineBIT_MASK(__bf)(((1U<<(bw##__bf))-1)<<(bs##__bf))

  #defineSET_BITS(__dst,__bf,__val)\

    ((__dst)=((__dst)&~(BIT_MASK(__bf)))|\

      (((__val)<<(bs##__bf))&(BIT_MASK(__bf))))

  SET_BITS(MCDR2,MCDR2_ADDRESS,RegisterNumber);

  函数和宏函数的区别就在于,宏函数占用了大量的空间,而函数占用了时间。

大家要知道的是,函数调用是要使用系统的栈来保存数据的,如果编译器里有栈检查选项,一般在函数的头会嵌入一些汇编语句对当前栈进行检查;同时,CPU也要在函数调用时保存和恢复当前的现场,进行压栈和弹栈操作,所以,函数调用需要一些CPU时间。

而宏函数不存在这个问题。

宏函数仅仅作为预先写好的代码嵌入到当前程序,不会产生函数调用,所以仅仅是占用了空间,在频繁调用同一个宏函数的时候,该现象尤其突出。

  D方法是我看到的最好的置位操作函数,是ARM公司源码的一部分,在短短的三行内实现了很多功能,几乎涵盖了所有的位操作功能。

C方法是其变体,其中滋味还需大家仔细体会。

第2招:

数学方法解决问题

  现在我们演绎高效C语言编写的第二招——采用数学方法来解决问题。

  数学是计算机之母,没有数学的依据和基础,就没有计算机的发展,所以在编写程序的时候,采用一些数学方法会对程序的执行效率有数量级的提高。

  举例如下,求1~100的和。

  方法E

  intI,j;

  for(I=1;I<=100;I++){

    j+=I;

  }

  方法F

  intI;

  I=(100*(1+100))/2

  这个例子是我印象最深的一个数学用例,是我的计算机启蒙老师考我的。

当时我只有小学三年级,可惜我当时不知道用公式N×(N+1)/2来解决这个问题。

方法E循环了100次才解决问题,也就是说最少用了100个赋值,100个判断,200个加法(I和j);而方法F仅仅用了1个加法,1次乘法,1次除法。

效果自然不言而喻。

所以,现在我在编程序的时候,更多的是动脑筋找规律,最大限度地发挥数学的威力来提高程序运行的效率。

第3招:

使用位操作

  实现高效的C语言编写的第三招——使用位操作,减少除法和取模的运算。

  在计算机程序中,数据的位是可以操作的最小数据单位,理论上可以用“位运算”来完成所有的运算和操作。

一般的位操作是用来控制硬件的,或者做数据变换使用,但是,灵活的位操作可以有效地提高程序运行的效率。

举例如下:

  方法G

  intI,J;

  I=257/8;

  J=456%32;

  方法H

  intI,J;

  I=257>>3;

  J=456-(456>>4<<4);

  在字面上好像H比G麻烦了好多,但是,仔细查看产生的汇编代码就会明白,方法G调用了基本的取模函数和除法函数,既有函数调用,还有很多汇编代码和寄存器参与运算;而方法H则仅仅是几句相关的汇编,代码更简洁,效率更高

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 农林牧渔 > 林学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1