B001-Atmega16-带电复位后不清0的.noinit变量
来源:互联网 发布:马蓉的淘宝店铺 编辑:程序博客网 时间:2024/04/30 08:24
《AVR单片机原理与GCC编程实践》P117讲到AVR代码段时,提到了.bss段中包含了一个很有意思的.noinit段。
.noinit段描述:
.bss段的变量在芯片启动的.init4阶段会被清0,但是定义在.bss的.noinit段中的变量在.init4阶段不会被清0。单片机不掉电复位后,.noinit段的这些变量的值依然存在,可以继续使用。
.noinit段的定义方法:int bar __attribute__ ((section (".noinit")));
不能指定初值,因为这些变量是在.bss段。.noinit段变量的复位测试:
也就是说、如果我在.noinit段定义一个变量,按下开发板的复位键(单片机不掉电复位),这个变量的值不会被清0。
下面是测试代码,我在.noinit段定义了变量bar,初值未知。
8bit的bar正好可以用连接在PORTB的8个LED灯来显示它的数值。
每次进入程序后、bar++,所以每按一次复位键,bar对应的8个LED灯的二进制数值就加1(二进制计数器)。
测试代码:
#include <avr/io.h>uint8_t bar __attribute__ ((section(".noinit")));int main(void){ bar++; DDRB = 0xFF; PORTB = 0xFF; PORTB = bar; while(1) { } return 0;}
测试结果:
我的8个LED是低推的,所以点亮的LED对应的引脚逻辑值是0,熄灭的LED对应的引脚逻辑值是1。
于是得到下面的结果:
程序下载到开发板后,这一次bar的初值是00000001(这次比较巧),每按一次复位键,bar的值都加1了。
重新下载程序后,bar的初值也会自己加1,也相当于单片机不掉电复位。
------------------------------------------------------------------------------------------------------------------------
使用.noinit特性测试BOD掉电:
2016.05.30
今天发现.noinit的特性还可以测试BOD掉电。
依然是使用上面的代码中的.noinit,加上PA0输出脉冲,同时查看PORTB的二进制计数器来得知复位次数。
代码如下:
int main(void){ // PA0为输出口 DDRA = (IO_OUTPUT << DDA0); // 记录复位次数 _noinit_using(); while(1) { // PA0拉高 PORTA = (1 << PA0); // 维持0.5秒 delay_ms(500); // PA0拉低 PORTA &= ~(1 << PA0); // 维持0.5秒 delay_ms(500); } return 0;}
其中的_noinit_using()如下:
volatile uint8_t v_noinit __attribute__ ((section(".noinit")));// ==========================================================================================================// 通过观察PORTB上的8位LED的状态得知复位次数// ==========================================================================================================void _noinit_using(void){ v_noinit++; // 8位LED,低推 DDRB = 0xFF; PORTB = 0xFF; PORTB = v_noinit;}
测试结果:
1、当前芯片BOD监测的电压是4.0V
2、使用.noinit可以测试复位次数(二进制计数器)
3、每次将电压源电压低到<3.7V,就会引发复位,而PORTB的二进制计数器就会加1
4、而且低到1V以下,复位后依然可以记住上一次的.noinit变量的值,大概是没有完全掉电的缘故
5、正常工作时可以看到PA0的脉冲,复位时中断。
------------------------------------------------------------------------------------------------------------------------
使用.noinit特性测试看门狗WDT:
在另一篇测试WDT效果的文章中,还是用这个.noinit+二进制计数器的方法测试了WDT的复位:
http://blog.csdn.net/manon_des_source/article/details/51540217
- B001-Atmega16-带电复位后不清0的.noinit变量
- B001-Atmega16-位域的汇编实现
- B001-Atmega16-数码管
- B001-Atmega16-SPI Flash
- B001-Atmega16-16位寄存器的读写步骤
- B001-Atmega16-PORTA的定义-(ques=1)
- B001-Atmega16-TFT-(未开始)
- B001-Atmega16-看门狗WDT-(ques=1)
- B001-Atmega16-定时器2-(ques=4)
- B001-Atmega16-定时器1-(ques=1)
- B001-Atmega16-汇编-地址空间分配
- B001-Atmega16-对齐模式和大小端
- B001-Atmega16-中断(GCC-AVR)-(ques=3)
- B001-Atmega16-公共buffer管理器(静态)-(未开始)
- 关于复位时的REG变量初始化
- Atmega16的定时器time0
- ATMEGA16定时器0
- ATmega16的定时器0、1、2的比较
- Sed命令的基本使用
- Java多线程中join方法的理解
- Chrome浏览器,搜索JS方法。
- Android小知识——关于Android内存、性能优化的一些细节
- vi查找行开头结尾
- B001-Atmega16-带电复位后不清0的.noinit变量
- SharePoint 2003 用REST方式访问列表 Filter等高级操作。
- 控制流
- 二分查找
- Linux网络底层收发探究
- 十招教你学会软件破解(转)
- 2.1 二元变量
- ALOHA
- Android小知识——动画的旋转