搜索
bottom↓
回复: 11

请教马老师,AVR单片机嵌入式系统原理与应用实践"403页usart中断收发数据的例子

[复制链接]

出0入0汤圆

发表于 2008-7-19 16:09:14 | 显示全部楼层 |阅读模式
看了一下午了,那几个地方还是不太懂!想麻烦马老师给讲解一下!
14.1.3 典型USART底层驱动+中间层软件结构示例 例子403页
这个例子我大体上可以看懂,但是感觉有好几个地方实在想不通!
1 对比384页的  USART接收中断服务程序
interrupt[USART-RXC]void usart_rx_isr(void)
{unsigned char status,data;
status=UCSRA;
data=UDR;
if((status&(FRAMING_ERROR|PARITY_ERROR|DATA_PVERRUN==0)
PORTA=led_7[data];}

404页的 USART接收中断服务程序设置了接收缓冲区,请问这里的unsigned char rx_buffer[RX_BUFFER_SIZE];是利用软件划出的一块缓冲区,还是硬件就有的缓冲区,和UDR是一个东西么?

2 bit rx_buffer_overflow;//接收缓冲区溢出标志
硬件上我找不到这个标志位
这里  bit rx_buffer_overflow; 的 bit是什么意思
如果是人为设定的一个标志位,那么系统如何知道bit rx_buffer_overflow=1就表示溢出呢!

3rx_wr_index,re_rd_index,rx_counter这些定义的变量,为何没有给初始值呢?我觉得是不是要赋给一个初始值0呢,否则当出现
rx_buffer[rx_wr_index]=data这样的语句时,因为没指定初始值,rx_wr_index一开始的值难道不会大于7么,比如10啊,而#define RX_BUFFER_SIZE 8,
数组元素应该是rx_buffer[0]到rx_buffer[7]

4这个问题是409页例子的,类似于问题2,就是bit UART_RecvFlag;这个标志位
if(! UART_RecvFlag)来判断是否允许接受一个新数据包,当正确接收到数据包后,将其置位,可是这不是硬件上的标志位,如何自动置位呢?请问程序从哪里能够看出来当正确接收到数据包时, UART_RecvFlag就会置位呢?


这几个问题我实在很不理解,希望马老师抽时间给我讲解一下,因为跨专业!周围实在没人懂!这里真心说一声谢谢!

出0入0汤圆

 楼主| 发表于 2008-7-19 16:21:25 | 显示全部楼层
数据缓冲器结构是一个线性的循环队列,由读、写和队列计数器3个指针控制,用于判断队列是否空、溢出,以及当前数据在队列中的位置。
这里的数据缓冲器结构到底是软件方式划出来的还是硬件的?

出0入0汤圆

发表于 2008-7-19 16:27:00 | 显示全部楼层
1 ram需要人工使用的。所以unsigned char rx_buffer是软件划出的缓存区。
  和UDR不是一个东西。
2 bit rx_buffer_overflow是定义个位变量。bit不是标准C关键字。这里是CVAVR支持的扩展C。
  人需要写程序来判断的rx_buffer_overflow。
3 可以给初值0.
  if(++rx_rd_index == RX_BUFFER_SIZE)rx_rd_index=0;就是判断边界的。并自动复位0;
(你似乎没有看懂缓存的作用。由于++和边界检测归0,所以缓存地址一直循环的【0 到 RX_BUFFER_SIZE】。简单的环形队列)
4 UART_RecvFlag其在USART接收中断中,当rx_counter==5且data==UART_END_STX时Uart_RecvFlag=1;




--------------
个人觉得楼主专业跨的大了。建议先弄本C语言和计算机原理看看。否则进度快不了。

出0入0汤圆

 楼主| 发表于 2008-7-19 16:54:57 | 显示全部楼层
那怎么办啊,c看了一遍,不过下个月就要天线仿真了,现在这边的东西还是看不懂!不管如何谢谢楼上,非常非常感激

出0入0汤圆

发表于 2008-7-19 16:59:27 | 显示全部楼层
有任务那就好办多了。

实践就好了。失败的多了就必定成功了。

楼主加油。
有问题就发贴。我和大家会尽力的。
建议自己能实验的就自己先试验,如果还解决不了的请统一发贴。问题集中。解决容易。

出0入0汤圆

 楼主| 发表于 2008-7-19 20:59:03 | 显示全部楼层
谢谢mljda ,真的,我很感动,不带一点点假话,非常的感动,其实每次问问题,我都是很害怕回帖,怕挨骂,怕大家说我问幼稚的问题,可是我实在是不懂,感觉自己年纪大了,学习效率明显不如以前,而且事情也多!现在关键是不理解编译器,书上的例子都是cavr,可是用得软件却必须是winavr,2者很多地方还是不同的,所以程序常常不能用!不管怎么样,mljda,您的鼓励让我非常之感动!

出0入0汤圆

发表于 2008-7-20 12:58:46 | 显示全部楼层
对于lz的努力和刻苦我表示敬佩和赞赏,也希望年轻的朋友们学习这样的精神。

但我从技术的角度上,还是要实事求是的说话。作为本书的编写目的之一,就是利用AVR所具备的优良性能和特点,为学习者向32位发展打基础。这就包括系统设计和软件设计能力的提高。

就拿UART讲,51也有该接口,但如果你看51的书,或一些简单入门的书,大部分只是介绍采用轮循方式的编程,这种方式实际上效率是非常低的。而采用中断+缓冲的方式应该讲是最能够发挥CPU的效率的方式了。可是要掌握这些好的方法,编程者软件能力就必须达到一定的水平,具备相应的基础。这是技术发展的必然结果。

因此,从软件角度讲,光会一点C的编程是远远不够的,其他的如《数据结构》(上面的例子里仅使用了数据结构中最简单的环型队列模型)的基础也需要具备。

就这个方面看,国内的硬件工程师在软件方面的基础和能力普遍较弱。

出0入0汤圆

 楼主| 发表于 2008-7-20 14:42:52 | 显示全部楼层
的确没学过数据结构,微机接口也没学过,现在要不然不求甚解,要不然就去补基础,我想自己只能尽力!谢谢大家和马老师的鼓励
我觉得如果现在放弃了,我可能以后再也不会有机会接触avr了,如果现在坚持下去,即使以后主业从是天线设计,但是至少我掌握了avr的技能,我想现在我还不会放弃,我要坚持下去!

出0入0汤圆

发表于 2009-6-29 17:06:24 | 显示全部楼层
1 ram需要人工使用的。所以unsigned char rx_buffer是软件划出的缓存区。
  和UDR不是一个东西。
2 bit rx_buffer_overflow是定义个位变量。bit不是标准C关键字。这里是CVAVR支持的扩展C。
  人需要写程序来判断的rx_buffer_overflow。
3 可以给初值0.
  if(++rx_rd_index == RX_BUFFER_SIZE)rx_rd_index=0;就是判断边界的。并自动复位0;
(你似乎没有看懂缓存的作用。由于++和边界检测归0,

请问问题3中,rx_rd_index如果没有赋初值,那么它得值是不是随机的,可以取0--255对不对?   但是如果这个数组大小为8,即RX_BUFFER_SIZE=8,则数组元素只能取0-7,   如果rx_rd_index未初始化  在if(++rx_rd_index == RX_BUFFER_SIZE)rx_rd_index=0;判断时就出现rx_wr_index>=RX_BUFFER_SIZE,例如rx_wr_index=8、9、10……,那么rx_buffer[rx_wr_index]不是已经出错了?那为什么这样操作?

我也是个AVR初学者,希望马老师给解释一下其中原因

出0入0汤圆

发表于 2009-6-30 09:05:12 | 显示全部楼层
关于变量是否要赋初值的问题,要根据所使用的编译器决定。

实际上现在大多数的这类专用的C编译器都会在你的代码前自动加上一段启动代码的,这段代码中要对堆栈指针、以及一些寻址寄存器等做初始化,其中包括变量初始化(为0)。因此你的代码中可以不对变量做初始化为0的工作。具体你应该查看所使用编译器的帮助书册。
下面是CVAVR中的说明:

Using an External Startup File

In every program the CodeVisionAVR C compiler automatically generates a code sequence to make the following initializations immediately after the AVR chip reset:

1.        interrupt vector jump table
2.        global interrupt disable
3.        EEPROM access disable
4.        Watchdog Timer disable
5.        external SRAM access and wait state enable if necessary
6.        clear the R2...R14 registers         ===> 变量清零部分!
7.        clear the SRAM                       ===> 变量清零部分!
8.        initialize the global variables located in SRAM
9.        initialize the Data Stack Pointer register Y
10.        initialize the Stack Pointer register SP
11.        initialize the UBRR register if necessary


The automatic generation of code sequences 2 to 8 can be disabled by checking the Code Generation|Use an External Startup Initialization File check box in the Project|Configure|C Compiler|Code Generation dialog window. The C compiler will then include, in the generated .asm file, the code sequences from an external file that must be named STARTUP.ASM . This file must be located in the directory where your main C source file resides.

You can write your own STARTUP.ASM file to customize or add some features to your program. The code sequences from this file will be immediately executed after the chip reset.
A basic STARTUP.ASM file is supplied with the compiler distribution and is located in the ..\BIN directory.
Here's the content of this file:

;CodeVisionAVR C Compiler

;(C) 1998-2006 Pavel Haiduc, HP InfoTech s.r.l.

;EXAMPLE STARTUP FILE FOR CodeVisionAVR V1.24.1 OR LATER

.EQU __CLEAR_START=0X60 ;START ADDRESS OF SRAM AREA TO CLEAR
                                ;SET THIS ADDRESS TO 0X100 FOR THE
                                ;ATmega128 OR ATmega64 CHIPS
        .EQU __CLEAR_SIZE=256   ;SIZE OF SRAM AREA TO CLEAR IN BYTES

        CLI                ;DISABLE INTERRUPTS
        CLR  R30
        OUT  EECR,R30        ;DISABLE EEPROM ACCESS

;DISABLE THE WATCHDOG
        LDI  R31,0x18
        OUT  WDTCR,R31
        OUT  WDTCR,R30

        OUT  MCUCR,R30        ;MCUCR=0, NO EXTERNAL SRAM ACCESS

;CLEAR R2-R14
        LDI  R24,13
        LDI  R26,2
        CLR  R27

__CLEAR_REG:
        ST   X+,R30
        DEC  R24
        BRNE __CLEAR_REG

;CLEAR SRAM
        LDI  R24,LOW(__CLEAR_SIZE)
        LDI  R25,HIGH(__CLEAR_SIZE)
        LDI  R26,LOW(__CLEAR_START)
        LDI  R27,HIGH(__CLEAR_START)
__CLEAR_SRAM:
        ST   X+,R30
        SBIW R24,1
        BRNE __CLEAR_SRAM

;GLOBAL VARIABLES INITIALIZATION
        LDI  R30,LOW(__GLOBAL_INI_TBL*2)
        LDI  R31,HIGH(__GLOBAL_INI_TBL*2)
__GLOBAL_INI_NEXT:
        LPM
        ADIW R30,1
        MOV  R24,R0
        LPM
        ADIW R30,1
        MOV  R25,R0
        SBIW R24,0

BREQ __GLOBAL_INI_END
        LPM
        ADIW R30,1
        MOV  R26,R0
        LPM
        ADIW R30,1
        MOV  R27,R0
        LPM
        ADIW R30,1
        MOV  R1,R0
        LPM
        ADIW R30,1
        MOV  R22,R30
        MOV  R23,R31
        MOV  R31,R0
        MOV  R30,R1
__GLOBAL_INI_LOOP:
        LPM
        ADIW R30,1
        ST   X+,R0
        SBIW R24,1
        BRNE __GLOBAL_INI_LOOP
        MOV  R30,R22
        MOV  R31,R23
        RJMP __GLOBAL_INI_NEXT
__GLOBAL_INI_END:

The __CLEAR_START and __CLEAR_SIZE constants can be changed to specify which area of SRAM to clear at program initialization.

The __GLOBAL_INI_TBL label must be located at the start of a table containing the information necessary to initialize the global variables located in SRAM. This table is automatically generated by the compiler.

==========================================================================================================
如果考虑标准或移植,你可以加上初始化语句,但在上面的情况下就是多余了,并且浪费了程序存储器的资源(单片机内部的资源是有限的,需要尽量节约)

学习使用单片机,以及单片机的编程与通常在PC上编程有许多的不同,要求具备的基础更加高,尤其是对于要想真正“会”用的人来讲。比如你应该(也可以讲是必须的)具备汇编的基础,掌握基本的使用汇编编写代码的能力和概念。这样你就知道,在汇编中必须要首先初始化堆栈指针寄存器,而在C中你就不要管了。这不是说使用C就不需要了,而是C编译器把常规的东西自动帮你加上去了。

出0入0汤圆

发表于 2009-6-30 18:34:38 | 显示全部楼层
哦,这样啊,又学到了一些新的知识,要不然还一直纳闷呢,  谢谢马老师的耐心解答。

出0入0汤圆

发表于 2010-7-4 13:45:48 | 显示全部楼层
mark
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-29 08:19

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表