打印
[国产单片机]

test2 等于 0x55,test 等于 test2与0x0F,结果等于 0x55 ?

[复制链接]
1566|31
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 panxiaoyi 于 2023-9-5 09:08 编辑


辉芒微单片机,代码如图,真不知道,是我的问题,还是编译器或者是单片机的流程就是这样的

main()
{
        MCUSYS_Init();
        GPIO_Init();
        GPIO_INT_Init();
        TIME1_Init();
        UART_Init();

//        GIE=1;                                    //全局中断使能
        PEIE=1;                                   //外设中断使能

        while(1)
        {     
                test=0;   

                test2=0x55;

                test=test2&0x0F;

                main_step=test;                       //然后再把中间变量赋值给用户变量,否则可能会被中断干扰
        }
}

运行结果如图




微信图片_20230905083714.png (437.47 KB )

微信图片_20230905083714.png

微信图片_20230905083600.png (463.76 KB )

微信图片_20230905083600.png

使用特权

评论回复
评论
xch 2023-9-5 17:58 回复TA
看样子 test 既是变量也是中间变量了。如果在中断用到test,在计算前关闭中断,计算结束打开中断。 或者定义一个volatile 中间变量作为过渡,让volatile tmp = test2 &0xf;test = tmp;倒一下脚,国足水平。 

相关帖子

沙发
ayb_ice| | 2023-9-5 09:05 | 只看该作者
是不是编译器认为变量值没有实际意义,优化了,建议变量加volatile试试

使用特权

评论回复
板凳
panxiaoyi|  楼主 | 2023-9-5 09:06 | 只看该作者
按照常规的理解,test 是不允许等于 0x55 的,这是因为我在中断里面需要判断这个 test 的值,然后才发现它的值有时候会等于 0x55。
也就是说 test=test2&0x0F; 这个语句
单片机运行的第一个步骤 test=test2;第二个步骤 test 才等于 0x05;
请问为什么会这样?为什么这个计算没有使用中间缓存来存储中间结果?这个真的好坑人。

使用特权

评论回复
地板
ysf| | 2023-9-5 09:15 | 只看该作者
你第一步,只是运行到那里,那一条语句实际还没运行,你应该运行到下一句再看才对,多想想自己的问题,不要认为人家做了几十年编译器会有低级的问题

使用特权

评论回复
5
panxiaoyi|  楼主 | 2023-9-5 09:18 | 只看该作者
ayb_ice 发表于 2023-9-5 09:05
是不是编译器认为变量值没有实际意义,优化了,建议变量加volatile试试

多谢解答
当时,我的语句是 main_step = test2 & 0x0F;  其中,test2 是串口接收到的数据(按道理不该被优化啊)
然后在中断里面发现 main_step 的数据有错误,然后才加多一个步骤的
实际的代码中不是这样的,只是便于大家的理解,我就用最简单的代码来测试
在真正的代码中,main_step 和 test2 都是有硬件用到的。test 是临时测试用的
编译器是默认优化级别

使用特权

评论回复
6
panxiaoyi|  楼主 | 2023-9-5 09:19 | 只看该作者
我加上 volatile 试试先

使用特权

评论回复
7
panxiaoyi|  楼主 | 2023-9-5 09:37 | 只看该作者
试过volatile了,暂时没有效果

微信截图_20230905093512.png (208.94 KB )

微信截图_20230905093512.png

使用特权

评论回复
8
840A| | 2023-9-5 10:11 | 只看该作者
你这个代码,InterruptData[]好像这个数组,中断要改的吧。果断volatile。
如果中断还改了别的东西,统统volatile。

使用特权

评论回复
9
dami| | 2023-9-5 10:13 | 只看该作者
当然你要走到下一步才显示结果啊。

使用特权

评论回复
10
coody| | 2023-9-5 10:39 | 只看该作者
仿真走到main_step=test;就会有结果。

使用特权

评论回复
11
ayb_ice| | 2023-9-5 10:42 | 只看该作者
panxiaoyi 发表于 2023-9-5 09:18
多谢解答
当时,我的语句是 main_step = test2 & 0x0F;  其中,test2 是串口接收到的数据(按道理不该被 ...

那几个变量都加volatile

使用特权

评论回复
12
lelouchly| | 2023-9-5 11:31 | 只看该作者
单片机是Cortex-M的还是8位的单片机,要看汇编指令。

使用特权

评论回复
13
zlf1208| | 2023-9-5 12:51 | 只看该作者
我一直在看汇编,但是不知道是几位的单片机,啥内核的

使用特权

评论回复
14
panxiaoyi|  楼主 | 2023-9-5 13:39 | 只看该作者
是辉芒微8位单片机,仿PIC的。型号是FT62F28x,访问不同的寄存器还要切换标志位的(请看第34句)

使用特权

评论回复
15
lelouchly| | 2023-9-5 14:03 | 只看该作者
我查了汇编指令跟PIC的也不同,只能通过上下文猜测,跟ARM不同的是,ARM是会把值先放在通用寄存器中计算好再放入内存中,但是看这个猜测是直接在内存上运算。你第一张图停的地方执行的STR 38H就是把0x55放在test的内存上,所以看到的值就是0x55。这样只能通过运算赋值时关闭中断源,运算完再开启,即代码保护区,或者通过中间变量运算完再赋值给test,赋值语句是单指令。

Snipaste_2023-09-05_13-58-33.png (319.91 KB )

Snipaste_2023-09-05_13-58-33.png

使用特权

评论回复
16
panxiaoyi|  楼主 | 2023-9-5 14:19 | 只看该作者
我完全新建了一个工程,这次的芯片是辉芒微 FT62F133 ,运行也会有错,全部代码如下

#include        "SYSCFG.h"

volatile unsigned char teat,teat2;

void interrupt ISR(void)
{
}

main()
{
        TRISA=0x00;
        PORTA=0x00;
       
        TRISC=0x00;
        PORTC=0x00;

        while(1)
        {
                teat2++;
               
                teat=teat2&0x03;
               
                if(teat) PORTC^=0xFF;
        }       
}
汇编代码如下
//Deviec:FT62F13X
//-----------------------Variable---------------------------------
                _teat                EQU                72H
                _teat2                EQU                73H
//-----------------------Variable END---------------------------------

                ORG                0000H
                BCR         PCLATH,3                 //0000         118A
                LJUMP         0BH                         //0001         380B
                ORG                0004H
                STR         7EH                         //0004         01FE
                SWAPR         STATUS,0                 //0005         0703
                STR         70H                         //0006         01F0
                LDR         PCLATH,0                 //0007         080A
                STR         71H                         //0008         01F1
                BCR         PCLATH,3                 //0009         118A
                LJUMP         24H                         //000A         3824
                BCR         PCLATH,3                 //000B         118A
                LJUMP         0DH                         //000C         380D
                CLRR         73H                         //000D         0173
                CLRR         STATUS                         //000E         0103
                BCR         PCLATH,3                 //000F         118A
                LJUMP         11H                         //0010         3811

                //;000.C: 12: TRISA=0x00;
                BSR         STATUS,5                 //0011         1A83
                CLRR         5H                         //0012         0105

                //;000.C: 13: PORTA=0x00;
                BCR         STATUS,5                 //0013         1283
                CLRR         5H                         //0014         0105

                //;000.C: 15: TRISC=0x00;
                BSR         STATUS,5                 //0015         1A83
                CLRR         7H                         //0016         0107

                //;000.C: 16: PORTC=0x00;
                BCR         STATUS,5                 //0017         1283
                CLRR         7H                         //0018         0107

                //;000.C: 19: {
                //;000.C: 20: teat2++;
                INCR        73H,1                         //0019         09F3

                //;000.C: 22: teat=teat2&0x03;
                LDR         73H,0                         //001A         0873
                STR         72H                         //001B         01F2
                LDWI         3H                         //001C         2A03
                ANDWR         72H,1                         //001D         02F2

                //;000.C: 24: if(teat) PORTC^=0xFF;
                LDR         72H,0                         //001E         0872
                BTSC         STATUS,2                 //001F         1503
                LJUMP         19H                         //0020         3819
                LDWI         FFH                         //0021         2AFF
                XORWR         7H,1                         //0022         0487
                LJUMP         19H                         //0023         3819
                ORG                0024H
                LDR         71H,0                         //0024         0871
                STR         PCLATH                         //0025         018A
                SWAPR         70H,0                         //0026         0770
                STR         STATUS                         //0027         0183
                SWAPR         7EH,1                         //0028         07FE
                SWAPR         7EH,0                         //0029         077E
                RETI                                         //002A         0009
                        END
运行结果如图

2.png (446.83 KB )

2.png

1.png (437.74 KB )

1.png

使用特权

评论回复
17
panxiaoyi|  楼主 | 2023-9-5 14:26 | 只看该作者
加了括号,如下,结果还是不行
teat=(teat2&0x03);

使用特权

评论回复
18
lelouchly| | 2023-9-5 14:33 | 只看该作者
panxiaoyi 发表于 2023-9-5 14:19
我完全新建了一个工程,这次的芯片是辉芒微 FT62F133 ,运行也会有错,全部代码如下汇编代码如下
运行结果 ...

按上面的汇编运行没错啊,你运行到那里已经执行了把test2的值0x87赋值给test了。

Snipaste_2023-09-05_14-31-35.png (268.05 KB )

Snipaste_2023-09-05_14-31-35.png

使用特权

评论回复
19
ayb_ice| | 2023-9-5 14:46 | 只看该作者
可以尝试关总中断试试

使用特权

评论回复
20
elife| | 2023-9-5 15:14 | 只看该作者
楼主的意思是,test这个变量,经过与0x0f运算,应该不会出现高位不为0的数据。 其实很多操作,都不是一步完成的,如果中断和大循环用全局变量通讯,一定要保证变量的原子操作。正确的做法应该是在更改该变量的所有语句前,都要关中断,执行后,开中断。除非能明确保证更改的操作是原子操作。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

49

主题

393

帖子

2

粉丝