找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1737|回复: 26
收起左侧

单片机C语言定义一个变量,如果不赋值,难道不是默认等于0嘛

  [复制链接]
ID:1022479 发表于 2023-2-9 20:40 | 显示全部楼层 |阅读模式

今天测试了一下按键控制蜂鸣器,具体程序见附件
想要实现按键按下,蜂鸣器响,按键按下,蜂鸣器关的功能
这个按道理很简单,可是实际操作时发现了程序里一个奇怪现象!!!
按键检测使用的是GPIO上拉输入模式,也就是空悬为高电平
这样按下按键之后检测到低电平刚好合适
按键一端接gnd,一端接PB0,PB11这里未使用
蜂鸣器是买的低电平驱动的小模块,3V到5V都兼容,这里只用到了PA1,PA2未使用
具体程序如下
这是蜂鸣器的初始化和翻转单片机程序
/********************************
#include"stm32f10x.h"                 // Device header

voidLED_Init(void) //也可用蜂鸣器低电平驱动代替
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitTypeDefGPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode= GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin= GPIO_Pin_1 | GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed= GPIO_Speed_50MHz;

GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_SetBits(GPIOA,GPIO_Pin_1 | GPIO_Pin_2);//初始设置高,防止开始低电平驱动蜂鸣器
}
void LED1_Turn(void) //蜂鸣器状态翻转程序
{
if(GPIO_ReadOutputDataBit(GPIOA,GPIO_Pin_1)==1)
{
GPIO_ResetBits(GPIOA,GPIO_Pin_1);
}
elseif(GPIO_ReadOutputDataBit(GPIOA,GPIO_Pin_1)==0)
{
GPIO_SetBits(GPIOA,GPIO_Pin_1);
}
}
*********************************************/
这是按键的相关程序
/*****************************************
#include"stm32f10x.h"                 // Device header
#include"Delay.h"
void Key_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitTypeDefGPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//上拉输入,悬空时为高电平,适合按键
GPIO_InitStructure.GPIO_Pin= GPIO_Pin_1 | GPIO_Pin_11;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//只对输出管用,这里输入随便填

GPIO_Init(GPIOB,&GPIO_InitStructure);
GPIO_SetBits(GPIOB,GPIO_Pin_1 | GPIO_Pin_11);//初始设置高,防止低电平驱动蜂鸣器
}

uint8_tGet_KeyNum(void)
{
uint8_t KeyNum = 0;//定义一个局部变量未检测为0,一定要加=0!!!
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1)== 0)
{
Delay_ms(20);//按下消抖
while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1) ==0);  //没有松手一直执行这条
Delay_ms(20);//松开消抖
KeyNum= 1;
}        
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11)== 0)
{
Delay_ms(20);//按下消抖
while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11) ==0);  //没有松手一直执行这条,用来确认松手
Delay_ms(20);//松开消抖
KeyNum= 11;
}
returnKeyNum;
}
**********************************************/
以下是main.c内的所有调用函数
/********************************************
#include"stm32f10x.h"                 // Device header
#include"Delay.h"
#include"LED.h"
#include"Key.h"

#define di 100


int main(void)
{
uint8_t KeyNum; //main函数内局部变量
LED_Init();
Key_Init();

while(1)
{
KeyNum= Get_KeyNum();

if(KeyNum==1) //PB1按键按下
{
LED1_Turn();//PA1翻转

}

}
}
*********************************************/
以上看上去确实没有问题对吧,实际上也没有问题,
因为这是我发现问题之后,修正过的程序
真正的问题在于,
原来的程序里只有一条语句与这不一样,
那就是按键的相关程序里面的
uint8_tGet_KeyNum(void)函数里的

第一行的uint8_tKeyNum = 0;  这样写达到了我的目的:按键按下,蜂鸣器响,按键按下,蜂鸣器关

原先我写的是uint8_t KeyNum;这样执行只有按着按键的时候蜂鸣器才会响???非常奇怪的现象

在我学习51单片机的过程中,老师一直对我说的是,如果定义一个变量,不给它赋初值,默认为0。
现在看起来好像是我理解有问题。。。。
uint8_tKeyNum = 0;和uint8_t KeyNum;有啥区别???
如果没有区别,为什么现象不一样???
局部变量里面定义了之后,
如果不赋值
Return 返回的难道不是0???是个随记数??也不对啊,求赐教?
不能理解,所以想请教各位大佬,如觉幼稚,请多多指教。

3-3按键控制LED.7z

174.89 KB, 下载次数: 3

回复

使用道具 举报

ID:883242 发表于 2023-2-10 00:14 | 显示全部楼层
全局变量默认才是0,如果你老师没讲错,那就是你记错了。

建议你看看《数据结构》这本书,递归那一章很好的说明了c语言局部变量是从哪里来的,如果你看懂了的话,就很容易知道为什么不是0。

另外,MDK是符合c语言标准的,C51不符合c语言标准,《数据结构》对局部变量的描写符合MDK,不符合C51。
回复

使用道具 举报

ID:1061331 发表于 2023-2-10 02:13 | 显示全部楼层
不确定。 但一般情况是,静态变量(static)与全局变量都默认为0,局部变量值不确定(很多情况下不为0)。
回复

使用道具 举报

ID:213173 发表于 2023-2-10 06:27 | 显示全部楼层
全局变量是个人专用卫生间,用后离开到下次再用内部环境不变。局部变量是公共卫生间,用后离开到下次再用内部环境不确定。可能卷纸抽空了,马桶还没冲。所以局部变量一定要先赋值再使用,函数退出时,将释放其空间。
回复

使用道具 举报

ID:596109 发表于 2023-2-10 09:04 | 显示全部楼层
通常情况下定义变量紧跟着就给赋个初值,就是为了防止函数每次调用时局部变量值的不确定
回复

使用道具 举报

ID:844772 发表于 2023-2-10 10:26 | 显示全部楼层
要看编译器的处理方式,不过只有静态变量才可能初始化为0,局部变量是动态的,就是随机数了。
回复

使用道具 举报

ID:146782 发表于 2023-2-10 11:28 | 显示全部楼层
定义变量后及时赋个初始值是个好的习惯
回复

使用道具 举报

ID:1039954 发表于 2023-2-10 11:29 | 显示全部楼层
最近刚好遇到这个问题,把局部转成静态变量就好了
回复

使用道具 举报

ID:1022479 发表于 2023-2-10 11:54 | 显示全部楼层
Hephaestus 发表于 2023-2-10 00:14
全局变量默认才是0,如果你老师没讲错,那就是你记错了。

建议你看看《数据结构》这本书,递归那一章很 ...

感谢大佬,学校安排的只有c语言程序设计,还是大一学的,现在看来还是学的太浅了
我会去学学数据结构的,这本书听说过,赶紧整一本回去恶补
回复

使用道具 举报

ID:1059013 发表于 2023-2-10 13:40 | 显示全部楼层
郑常椿 发表于 2023-2-10 11:54
感谢大佬,学校安排的只有c语言程序设计,还是大一学的,现在看来还是学的太浅了
我会去学学数据结构的 ...

我单片机C编程搞得不错,但是从来不看什么数据结构,如何?
回复

使用道具 举报

ID:883242 发表于 2023-2-10 16:58 | 显示全部楼层
c编程搞得不错有两种,一种是真的不错,另一种是井蛙级搞得不错,楼上显然是后一种。
回复

使用道具 举报

ID:883242 发表于 2023-2-10 20:47 | 显示全部楼层
补充一下,如果楼主搞过Windows编程,会遇到著名的“手持两把锟斤拷,口中疾呼烫烫烫”的问题,此问题的根源就是初始化以后的堆栈里面并不是0。
回复

使用道具 举报

ID:1034262 发表于 2023-2-10 22:01 | 显示全部楼层
不一定,所以一定要养成清内存或给变量初值的习惯。
回复

使用道具 举报

ID:879348 发表于 2023-2-13 14:18 | 显示全部楼层
当然不是,RAM上是随机值,很多单片机,包括51单片机,STM32单片机等进入mian前还有一段代码初始化
回复

使用道具 举报

ID:130230 发表于 2023-2-13 18:00 | 显示全部楼层
局部变量是定义在栈上的,如果不加static修饰在退出函数后会释放该空间。所以这个变量每次进入函数都是不同的地址,所以如果这个地址刚好被某个函数使用过那么初始值就不是0.
回复

使用道具 举报

ID:130230 发表于 2023-2-13 18:03 | 显示全部楼层
郑常椿 发表于 2023-2-10 11:54
感谢大佬,学校安排的只有c语言程序设计,还是大一学的,现在看来还是学的太浅了
我会去学学数据结构的 ...

这不是数据结构的内容,是链接和作用域的内容。看一遍c primer plus后把基础搞清楚再看数据结构吧。尤其是指针要搞透彻。
回复

使用道具 举报

ID:883242 发表于 2023-2-15 17:10 | 显示全部楼层
对于标准c语言来说,局部变量是在堆栈之上,跟链接和作用域没有一毛钱关系,局部变量是怎么来的,又是怎么没的,只有《数据结构》里面递归一节说的最清楚。

对于不遵守标准的野路子编译器,比如Keil C51才跟链接有关。
回复

使用道具 举报

ID:130230 发表于 2023-2-16 17:57 | 显示全部楼层
Hephaestus 发表于 2023-2-15 17:10
对于标准c语言来说,局部变量是在堆栈之上,跟链接和作用域没有一毛钱关系,局部变量是怎么来的,又是怎么 ...

你确定你学过C语言?数据结构怎么和c语言绑定了搞不懂。。。
回复

使用道具 举报

ID:883242 发表于 2023-2-16 19:11 | 显示全部楼层
jizhongbiao 发表于 2023-2-16 17:57
你确定你学过C语言?数据结构怎么和c语言绑定了搞不懂。。。

c语言教科书一般不会告诉你局部变量是怎么来的,又是怎么没的,《数据结构》会讲。

你说一本讲局部变量来历的教科书好了。
回复

使用道具 举报

ID:844772 发表于 2023-2-16 23:24 来自手机 | 显示全部楼层
Hephaestus 发表于 2023-2-16 19:11
c语言教科书一般不会告诉你局部变量是怎么来的,又是怎么没的,《数据结构》会讲。

你说一本讲局部变 ...

学没学过数据结构是程序员的一个分水岭,你没法跟没学过数据结构的人讲清楚原因的,但可以出个题,比如如何写个走迷宫程序
回复

使用道具 举报

ID:59202 发表于 2023-2-17 09:28 | 显示全部楼层
养成良好的编程习惯是对的,否则会经常出现一些让人头疼的小问题
回复

使用道具 举报

ID:883242 发表于 2023-2-17 19:30 | 显示全部楼层
glinfei 发表于 2023-2-16 23:24
学没学过数据结构是程序员的一个分水岭,你没法跟没学过数据结构的人讲清楚原因的,但可以出个题,比如如 ...

夏虫不可语冰,井蛙不可语海。
回复

使用道具 举报

ID:146878 发表于 2023-2-17 21:58 | 显示全部楼层
定义变量随手赋值是好习惯,很多低端单片机,是不处理内存初始状态的。
回复

使用道具 举报

ID:965301 发表于 2023-2-20 17:36 | 显示全部楼层
单片机C语言变量默认值有可能不为0,是随机数,给编译器有关。
回复

使用道具 举报

ID:130230 发表于 2023-2-21 18:01 | 显示全部楼层
Hephaestus 发表于 2023-2-16 19:11
c语言教科书一般不会告诉你局部变量是怎么来的,又是怎么没的,《数据结构》会讲。

你说一本讲局部变 ...

所有的教科书都会讲啊
回复

使用道具 举报

ID:130230 发表于 2023-2-21 18:03 | 显示全部楼层
Hephaestus 发表于 2023-2-15 17:10
对于标准c语言来说,局部变量是在堆栈之上,跟链接和作用域没有一毛钱关系,局部变量是怎么来的,又是怎么 ...

你所谓的递归讲了是恰好因为递归使用了栈,栈是作用域的内容啊。。。算了这论坛水平是在是有限。
回复

使用道具 举报

ID:130230 发表于 2023-2-21 18:04 | 显示全部楼层
glinfei 发表于 2023-2-16 23:24
学没学过数据结构是程序员的一个分水岭,你没法跟没学过数据结构的人讲清楚原因的,但可以出个题,比如如 ...

没学过数据结构的能叫程序员?还写个迷宫哈哈哈大一的?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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