关于AVR单片机的程序问题
#definePIN_RXD0//PD0RXD#definePIN_TXD1//PD1TXD#defineLED00//PB0#defineLED11//PB1#defi...
#define PIN_RXD 0 //PD0 RXD
#define PIN_TXD 1 //PD1 TXD
#define LED0 0 //PB0
#define LED1 1 //PB1
#define LED2 3 //PB3
#define BAUDRATE 9600 //波特率
//#define F_CPU 7372800
#define LED0_ON() PORTB|= (1<<LED0)
#define LED0_OFF() PORTB&=~(1<<LED0)
#define LED1_ON() PORTB|= (1<<LED1)
#define LED1_OFF() PORTB&=~(1<<LED1)
#define LED2_ON() PORTB|= (1<<LED2)
#define LED2_OFF() PORTB&=~(1<<LED2)
//全局变量
//如果变量会在中断服务程序中被修改,须加volatile限定
volatile unsigned char FLAG; //按键标志
volatile unsigned char PC_COMMAND;
volatile unsigned char RX_BUFFER[16];
volatile unsigned char RX_index;
void put_c(unsigned char c) //发送采用查询方式
{
while( !(UCSRA & (1<<UDRE)) );
UDR=c;
}
void put_s(unsigned char *ptr)
{
while (*ptr)
{
put_c(*ptr++);
}
put_c(0x0D);
put_c(0x0A); //结尾发送回车换行
}
SIGNAL(SIG_USART_RECV) //串口接收中断服务程序
{
PC_COMMAND=UDR;
switch(PC_COMMAND)
{
case '0': //0x30 ASCII '0'
LED0_ON();
put_s("用户输入0#指令");
break;
case '1':
LED1_ON();
put_s("用户输入1#指令");
break;
case '2':
LED0_OFF();
LED1_OFF();
FLAG=!FLAG;
put_s("用户输入2#指令");
break;
default:
put_s("用户输入的指令无效!");
break;
}
RX_BUFFER[RX_index]=PC_COMMAND; //保存数据到数组里面
RX_index++;
if (RX_index>=16) RX_index=0; //防止数组溢出
}
void init_USART(void)//USART 初始化
{
//USART 9600 8, n,1 PC上位机软件(超级终端等)也要设成同样的设置才能通讯
UCSRC = (1<<URSEL) | 0x06;
//异步,8位数据,无奇偶校验,一个停止位,无倍速
UCSRA = 0x00;
UCSRB = (1<<RXCIE)|(1<<RXEN)|(1<<TXEN);
//使能接收中断,使能接收,使能发送
}
int main(void)
{
//上电默认DDRx=0x00,PORTx=0x00 输入,无上拉电阻
PORTA =0xFF; //不用的管脚使能内部上拉电阻。
PORTC =0xFF;
DDRB = (1<<LED2)|(1<<LED1)|(1<<LED0); //输出
PORTB =~((1<<LED2)|(1<<LED1)|(1<<LED0)); //低电平,灯灭
DDRD =(1<<PIN_TXD); //TXD为输出
PORTD =0xFF;
FLAG=0;
init_USART();
put_s("你好!");
put_s("这是一个简单的串口实验程序");
put_s("你可以在电脑上的超级终端程按下[0][1][2]按键,模拟用户板上的按键操作");
sei(); //使能全局中断
while (1)
{
while (FLAG==0) pro_coammand();
LED2_ON(); //如果FLAG不加volatile限定(即has_volatile=0),程序将永远都运行不到这里。
while (FLAG!=0) pro_coammand();
LED2_OFF();
}
}
这段代码中有一个地方我不懂.
"while (FLAG==0) pro_coammand();
LED2_ON(); //如果FLAG不加volatile限定(即has_volatile=0),程序将永远都运行不到这里。"
为什么加了volatile就可以了,while (FLAG==0) pro_coammand();这一句我觉得会重复执行 pro_coammand()那么屏幕上会不断显示之前输入的数.我想知道volatile变量的内存执行机制是怎样的?谢谢.如果答案满意我会追加30分. 展开
#define PIN_TXD 1 //PD1 TXD
#define LED0 0 //PB0
#define LED1 1 //PB1
#define LED2 3 //PB3
#define BAUDRATE 9600 //波特率
//#define F_CPU 7372800
#define LED0_ON() PORTB|= (1<<LED0)
#define LED0_OFF() PORTB&=~(1<<LED0)
#define LED1_ON() PORTB|= (1<<LED1)
#define LED1_OFF() PORTB&=~(1<<LED1)
#define LED2_ON() PORTB|= (1<<LED2)
#define LED2_OFF() PORTB&=~(1<<LED2)
//全局变量
//如果变量会在中断服务程序中被修改,须加volatile限定
volatile unsigned char FLAG; //按键标志
volatile unsigned char PC_COMMAND;
volatile unsigned char RX_BUFFER[16];
volatile unsigned char RX_index;
void put_c(unsigned char c) //发送采用查询方式
{
while( !(UCSRA & (1<<UDRE)) );
UDR=c;
}
void put_s(unsigned char *ptr)
{
while (*ptr)
{
put_c(*ptr++);
}
put_c(0x0D);
put_c(0x0A); //结尾发送回车换行
}
SIGNAL(SIG_USART_RECV) //串口接收中断服务程序
{
PC_COMMAND=UDR;
switch(PC_COMMAND)
{
case '0': //0x30 ASCII '0'
LED0_ON();
put_s("用户输入0#指令");
break;
case '1':
LED1_ON();
put_s("用户输入1#指令");
break;
case '2':
LED0_OFF();
LED1_OFF();
FLAG=!FLAG;
put_s("用户输入2#指令");
break;
default:
put_s("用户输入的指令无效!");
break;
}
RX_BUFFER[RX_index]=PC_COMMAND; //保存数据到数组里面
RX_index++;
if (RX_index>=16) RX_index=0; //防止数组溢出
}
void init_USART(void)//USART 初始化
{
//USART 9600 8, n,1 PC上位机软件(超级终端等)也要设成同样的设置才能通讯
UCSRC = (1<<URSEL) | 0x06;
//异步,8位数据,无奇偶校验,一个停止位,无倍速
UCSRA = 0x00;
UCSRB = (1<<RXCIE)|(1<<RXEN)|(1<<TXEN);
//使能接收中断,使能接收,使能发送
}
int main(void)
{
//上电默认DDRx=0x00,PORTx=0x00 输入,无上拉电阻
PORTA =0xFF; //不用的管脚使能内部上拉电阻。
PORTC =0xFF;
DDRB = (1<<LED2)|(1<<LED1)|(1<<LED0); //输出
PORTB =~((1<<LED2)|(1<<LED1)|(1<<LED0)); //低电平,灯灭
DDRD =(1<<PIN_TXD); //TXD为输出
PORTD =0xFF;
FLAG=0;
init_USART();
put_s("你好!");
put_s("这是一个简单的串口实验程序");
put_s("你可以在电脑上的超级终端程按下[0][1][2]按键,模拟用户板上的按键操作");
sei(); //使能全局中断
while (1)
{
while (FLAG==0) pro_coammand();
LED2_ON(); //如果FLAG不加volatile限定(即has_volatile=0),程序将永远都运行不到这里。
while (FLAG!=0) pro_coammand();
LED2_OFF();
}
}
这段代码中有一个地方我不懂.
"while (FLAG==0) pro_coammand();
LED2_ON(); //如果FLAG不加volatile限定(即has_volatile=0),程序将永远都运行不到这里。"
为什么加了volatile就可以了,while (FLAG==0) pro_coammand();这一句我觉得会重复执行 pro_coammand()那么屏幕上会不断显示之前输入的数.我想知道volatile变量的内存执行机制是怎样的?谢谢.如果答案满意我会追加30分. 展开
1个回答
展开全部
你这个问题其实和AVR单片机没关系,任何一个MCU都可以采用类似的代码。
在C语言里,有值传递这个概念,这是因为编译器会优化程序,为变量做一个拷贝值。这样呢,cpu在计算这个值时,直接去取拷贝值,而不用去计算这个值的地址,然后寻址,再去取这个值,从而节省了一定的指令周期。但是,有一个隐患,这个变量的拷贝值和这个变量的真实值不一定是一样的。比如,当中断发生时,cpu会将所有变量入栈去执行中断服务子程序,然后返回到主程序。在这个过程中,如果中断服务子程序修改了某个公共变量,主程序是不知道的,因为主程序会调用入栈前的拷贝值。
volatile就是告诉编译器,不要优化,不要拷贝,而是让cpu寻址取值。
FLAG是一个全军变量,它既在主程序中使用,又在串口接收中断服务程序中使用,所以要用volatile修饰,告诉cpu取真实值
在C语言里,有值传递这个概念,这是因为编译器会优化程序,为变量做一个拷贝值。这样呢,cpu在计算这个值时,直接去取拷贝值,而不用去计算这个值的地址,然后寻址,再去取这个值,从而节省了一定的指令周期。但是,有一个隐患,这个变量的拷贝值和这个变量的真实值不一定是一样的。比如,当中断发生时,cpu会将所有变量入栈去执行中断服务子程序,然后返回到主程序。在这个过程中,如果中断服务子程序修改了某个公共变量,主程序是不知道的,因为主程序会调用入栈前的拷贝值。
volatile就是告诉编译器,不要优化,不要拷贝,而是让cpu寻址取值。
FLAG是一个全军变量,它既在主程序中使用,又在串口接收中断服务程序中使用,所以要用volatile修饰,告诉cpu取真实值
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询