2011年12月22日星期四

The problem of AVR USART using USRE interrupt

"The Data Register Empty (UDREn) Flag indicates whether the transmit buffer is ready to receive
new data. This bit is set when the transmit buffer is empty, and cleared when the transmit buffer
contains data to be transmitted that has not yet been moved into the Shift Register. For compatibility with future devices, always write this bit to zero when writing the
UCSRnA Register.
When the Data Register Empty Interrupt Enable (UDRIEn) bit in UCSRnB is written to one, the USART Data Register Empty Interrupt will be executed as long as UDREn is set (provided thatn global interrupts are enabled). UDREn is cleared by writing UDRn. When interrupt-driven data transmission is used, the Data Register Empty interrupt routine must either write new data to UDRn in order to clear UDREn or disable the Data Register Empty interrupt, otherwise a new interrupt will occur once the interrupt routine terminates."

此中断与TXC中断不同,如果在发送一套数据后,发送寄存器会一直空的,这样UDRE中断会一直存在,解决方法就是,在发完后关上UDRE中断。

如果一直产生中断的话,会影响后面的中断的进入。

PS:2011年底,重写飞机上的AVR程序,把以前的usart接收用的TXC中断改为UDRE中断,导致这个问题的发生,被困扰了4天啊。。。基本上都是通宵的。。。。

2011年12月12日星期一

const指针的一些总结

前两天在网上看到华为的一些笔试题,对基础的掌握仍然是这种大公司所重视的。其间对指针掌握的要求比较多,有一道是关于const指针的。看到那道题,回来整理了一些有关const指针的内容,分享一下。

  const说明指针变量,组合的情况可能会显得很复杂。使用指针时要涉及两个目标,即指针本身和指针所指的对象。关于const指针变量,可归结为以下三种:
  1.指向常量的指针变量;
  2.常指针变量;
  3.指向常量的常指针变量。
  下面来分别谈谈这三种情况。

一、指向常量的指针变量:
声明格式: const type * var_name;
或 type const * var_name;
特点: 可改值。
  将指针声明冠以const,使指向的对象为常量,而不是指针为常量。注意:指向常量的指针不一定指向真正的常量,它也可以指向常量,只是从该指针的角度来看,它所指向的对象是常量,通过该指针不能修改它指向的对象。它还可以指向其它的对象,可以不初始化。
-----eg:
int a = 0,b = 1;
const int c = 3;
const int* pi; //等同于 (const int*) pi;
pi = &a;
*pi = 10; //错误:不能修改它指向的对象。
a = 10;
pi = &b;
*pi = &b;
*pi = 20; //错误:不能修改它指向的对象。
b = 20;
pi = &c;
*pi = &c;
*pi = 30; //错误:不能修改它指向的对象。
-----eg2:
const char* pc = "asdf";
pc[3] = 'a'; //错误:不能修改它指向的对象。
pc = "ghik";
-----eg3:
const char* step[3] =
{"left","right","hop"};
step[2] = "skip";
step[2][1] = 'i'; //错误:不能修改它指向的对象。

二、常指针常量:
声明格式: type* const var_name;
特点: 可改对象。
  要把指针本身,而不是它指向的对象声明为常量,采用运算符 *const,必须初始化,通过该指针可以修改它指向的对象,但它不可以指向其他的对象。
-----eg:
int a = 0,b = 1;
int* const pi = &a; //等于 int* (const pi) = &a;
*pi = 10;
pi = &b; //错误:pi本身为常量,不能指向其他对象。

三、指向常量的常指针变量:
声明格式: const type * const var_name;
特点: 值与对象均不能改。
  要使两个目标都是常量,两者都要声明为 const 。
eg:
int a = 0,b = 1;
const int c = 3;
const int* const pi = &a; //相当于: (const int*)(const pi) = &a;
*pi = 10; //错误:不能修改它的对象。
a = 10;
pi = &b; //错误:不能指向其它对象。
eg2:
const char* const pc = "asdf";
pc[3] = 'a'; //错误:不能修改它的对象。
pc = "ghik"; //错误:不能指向其它对象。
eg3:
const char* const step[3] =
{"left","right","hop"};
step[2] = "skip"; //错误:不能指向其它对象。
step[2][1] = 'i'; //错误:不能修改它的对象。

  一般的,当声明中出现 const 描述符时,它修饰的是紧跟其后的声明元素或者在 const 成员函数声明中函数的 this 指针。
  注意:可以将变量的地址赋给指向常量的指针变量,不会因此有什么害处,但是,常量的地址不能赋给无约束的指针。
eg:
int a = 1;
const int c = 2;
const int* p1 = &c;
const int* p2 = &a;
int* p3 = &c; //非法!
int* const p4 = &c; //非法! 指针常量 p4 能够改值。
const int* const p5 = &c;