MSP430 单片机内指针或结构体赋值为NULL,却有默认值的解决办法

发布者:小九分析仪最新更新时间:2022-10-18 来源: csdn关键字:MSP430  单片机  结构体  赋值 手机看文章 扫描二维码
随时随地手机看文章

在几天前的一个项目里我用单片机做了一个小的音游系统(暂时还没发出来),在里面遇到了很诡异的事情,首先这是我的音符结构体(就是音游里面能击打的那种音符):


typedef struct note note;

struct note {

int notetype;//1为单键,0为长键

unsigned long create_time;//创建时间,单位为毫秒

unsigned int length;//音符长度,每次判定

        unsigned int n_length;//现在音符剩余长度

};

然后我去网上毛(?)了一个c语言的队列文件,这里也附上链接:https://blog.csdn.net/qq_44785014/article/details/104089691


里面只需要把数据类型改一下就可以用了,我就习惯性地把数据类型改成了结构体指针

然后在主程序的全局变量中使用了队列结构体指针,想着他这个文件里的函数不都是调用的队列指针吗(比如查询是否为空就是void QueueEmpty(Queue* q)),那我设置个队列指针不就免得每次加个取值符了吗。


然后就出了一堆bug...


首先就是队列的操作函数用不了,找了很久的bug发现它如果参数是Queue*的,就得创建Queue结构体,然后传地址进去,比如:


Queue q;

QueueEmpty(&q);


虽然有调查过,但我一个基础不是很好的人确实不知道是不是单片机导致出这样的问题,但好了现在队列能用了,然后就遇到了我标题提到的bug,我明明什么结构体都没往队列里放,但是队列里就是自带一个奇怪的结构体。


简单来讲就是我初始化队列为NULL,但用QueueEmpty获得的结果是队列非空,取队列头还能取出来,值还是确定的(多次调试发现取出来的结构体的值完全一样),这就导致游戏一开始他就疯狂miss,因为队列里有音符而且不停超时。


略过好几个小时的bug调试,我终于想到我当时把结构体指针note*作为了队列的元素,而指针这东西在单片机里我感觉就是薛定谔的猫一样,有时能用有时不能用,于是我试着把队列元素换成结构体,又改了主函数里的一大堆红点

在把队列元素换成结构体note之后,再把主函数里一大堆红点全改完,再次在测试程序里调用一下QueueEmpty函数,唉,成了!队列是空的了!


激动地把在正常程序里调用,系统终于正常了。


具体为什么为出现这样的问题我最后也没能理解,如果从调试的顺序来讲的话,我是创建了一个队列结构体变量(Queue q),然后用文件里的初始化函数对其进行初始化(QueueInit(&q)),然后用查询队列空函数(QueueEmpty(&q))查询其是否为空,结果显示为非空,其文件内使用到的东西如下:


typedef struct note note;

struct note {

int notetype;//1为单键,0为长键

unsigned long create_time;//创建时间,单位为毫秒

unsigned int length;//音符长度,每次判定

    unsigned int n_length;//现在音符剩余长度

};

 

typedef note* QuDataType;//这里使用结构体指针为队列元素

// 链式结构:表示队列

typedef struct QListNode

{

struct QListNode* _next;

QuDataType _data;

}QueueNode;

// 队列的结构

typedef struct Queue

{

QueueNode* _front;

QueueNode* _rear;

}Queue;

//初始化队列结构

void QueueInit(Queue* q)

{

q->_front = NULL;

q->_rear = NULL;

}

//判断队列是否为空

int QueueEmpty(Queue* q)

{

return (q->_front == NULL);   //为空,返回1

}


也就是建立了一个带有结构体a的指针和结构体n的指针的结构体a,又用结构体b封装了两个结构体a的指针,初始化时将b的两个指针赋值为NULL,判断是否为空时查看其中一个指针是否为NULL,此时q->_front不是NULL,且里面的数据变量带有初值。


而如果把结构体n的指针换成结构体n,则q->_front是NULL,没有数据在里面。


关键字:MSP430  单片机  结构体  赋值 引用地址:MSP430 单片机内指针或结构体赋值为NULL,却有默认值的解决办法

上一篇:msp430 while语句的超自然现象
下一篇:MSP430F5529系统升压与时钟配置

推荐阅读最新更新时间:2024-11-01 19:12

分时操作系统思想在单片机编程中的实现
摘要:提出基于分时系统思想的单片机系统设计方案,给出一具体应用的实例以及详细的实现方法。 关键词:分时操作系统 单片机系统 作业调度 指针 前言   作为嵌入式系统主控单元——单片机,其软件往往是一个微观的实时操作系统,且大部分是为某种应用而专门设计的。系统程序有实时过程控制或实时信息处理的能力,要求能够及时响应随机发生的外部事件并对该事件做出快速处理。而分时操作系统却是把CPU的时间划分成长短基本相同的时间区间,即“时间片”,通过操作系统的管理,把这些时间片依次轮流地分配给各个用户使用。如果某个作业在时间片结束之前,整个任务还没有完成,那么该作业就被暂停下来,放弃CPU,等待下一轮循环再继续做。此时CPU又分配给另一个作
[单片机]
51单片机:定时器
定时器:单条指令时间(us) = 1/单片机频率*单条指令时钟周期 TH0和TL0共16位,最多只能表示65535,所以要设定一个Base值,再利用循环多计数几次 比如0.002s:0.02 = (1/11.0592M * 12)*指令个数,指令个数 = 0.02(1/11.0592M * 12) = 0.018432 因为频率用的是M,所以结果0.018432*1000000 = 18432 使用16位寄存器的情况下,TH0和TL初始值:65536 - 18432 = 47104 = 0xB8 00 编写定时器延时函数: #include sbit LED = P0^0; void Delay(un
[单片机]
51单片机实验15:DS1302时钟模块应用
开发板DS1302模块电路图如下: 目的:单片机查询DS1302时钟模块时间,并将其显示在数码管上。 DS1302的初始化时间为2019年1月1日12:00(星期二) #include reg52.h #include dse1302.h sbit LSA=P2^2; sbit LSB=P2^3; sbit LSC=P2^4; uc code x ={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; uc tim ; void delay(uc x) { uc i,j; for(i=1;i =x;i++) for(j=1;j =110;j++);
[单片机]
51<font color='red'>单片机</font>实验15:DS1302时钟模块应用
用8031单片机控制的数字钟
数字电子钟的设计方法有多种,例如,可用中小规模集成电路组成电子钟;也可以利用专用的电子钟芯片配以显示电路及其所需要的外围电路组成电子钟;还可以利用单片机来实现电子钟等等。这些方法都各有特点,其中,利用单片机实现的电子钟具有编程灵活,便于电子钟功能的扩充,即可用该电子钟发出各种控制信号,精确度高等特点。 所设计的电子钟有以下功能: 1. 24小时制时间显示。 2. 可随时进行时间校对。 3. 整点报时。 4. 闹钟功能。 为了节约制作硬件的开支,我们利用单片机开发机上的硬件资源,开发了电脑数字钟的软件。该数字钟由8031单片机控制,采用24小时制计时,利用开发机上的六个LED显示器来显示时、分和秒,使用P1端口中的P1.0端口线
[单片机]
用8031<font color='red'>单片机</font>控制的数字钟
MSP430单片机学习小记1--基础定时器
基于MSP430单片机,TI公司采用的是模块化的内部结构,每个模块,在各个不同型号的单片机内都是相同的,相同的寻址,相同的操作方式,模块有限,于是一个一个开始进行整理。 第一个模块:基础定时器 参考资料:数据手册 ,使用手册 ,示例程序,以及那份特别特别有用的头文件。 Exampli Code: 进入中断示例程序 /************************************************************/ 1;时钟源为ACLK,为单片机提供1/4S定时中断,LCD提供512HZ刷新频率 BTCTL=BT_ADLY_250+BT_fLCD_512; //250MS延时加512HZ刷新频
[单片机]
如何在STM32单片机中加入RDP功能
沿用之前CM3核的STM32F10X系列的加入RDP功能,之后在Segger的Unsecured Chip或者Unlock STM32的Cmd无法进行去除RDP,而Unlock STM32则提示无法识别该型号。尝试了很多方法,依然无法对其进行Remove RDP,估计是型号比较新,Segger还未完全支持吧。所用 的Segger为官方最新的Release跟Beta版本V4.65d跟V4.67c/ 估计可用的方法有以下三种: 1、配置Boot区,用System bootloader启动,Boot1 = 0,Boot0=1,然后用串口ISP的A上位机对其进行去除读保护; 2、配置Boot区,用SRAM运行程序,在SRAM的主程序中
[单片机]
MSP430F149按键中断寄存器配置
P20~P23为LED,P11为按键。按下为低电平。 使用中断函数按下一次按键则LED状态反转一次。 #include io430.h #include in430.h void select_xt2(void){ unsigned char i; /*------选择系统主时钟为8MHz-------*/ BCSCTL1 &= ~XT2OFF; do{ IFG1 &= ~OFIFG; //清除晶振失败标志 for (i = 0xFF; i 0; i--); //等待8MHz晶体起振 }while ((IFG1 & OFIFG));
[单片机]
基于80C196的高精度、低成本A/D转换器实现
0 引言 在智能化仪表中,A/D转换器直接影响仪表的性能,A/D转换器的性能主要在两个方面,转换精度和转换时间。目前常用的有逐次逼近型转换器、并行转换器、双积分转换器等。其中,双积分A/D转换器因为转换精度高、抗干扰性能强,并且价格相对较低,在数字测温仪表以及工业现场的慢变信号数据采集中得到非常广泛的应用。但是双积分A/D转换器在实际应用中仍有不足之处。由于其工作过程中零点漂移误差、以及电容充放电造成的非线性,使得其如要获得较高的精度,对电路中运放、电阻、电压基准等元件的精确度和温漂系数等指标的要求就非常高,特别是它不适合快变信号的数据采集。而适合快变信号的高精度并行转换器的价格太高,如12位精度的AD7874价格就十分昂贵
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved