程序问答   发布时间:2022-06-02  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了STM32F407 在写入 CAN_BTR 寄存器时的奇怪行为大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

如何解决STM32F407 在写入 CAN_BTR 寄存器时的奇怪行为?

开发过程中遇到STM32F407 在写入 CAN_BTR 寄存器时的奇怪行为的问题如何解决?下面主要结合日常开发的经验,给出你关于STM32F407 在写入 CAN_BTR 寄存器时的奇怪行为的解决方法建议,希望对你解决STM32F407 在写入 CAN_BTR 寄存器时的奇怪行为有所启发或帮助;

我定义了以下用户类型:

typedef struct
{
    union
    {
        struct
        {
            uint32_t BRP :10;
            uint32_t Reserved_1 :6;
            uint32_t TS1 :4;
            uint32_t TS2 :3;
            uint32_t Reserved_2 :1;
            uint32_t SJW :2;
            uint32_t Reserved_3 :4;
            uint32_t LBKM :1;
            uint32_t SILM :1;

        };
        uint32_t reg;
    };
}__attribute__((packed,aligned(1))) _CAN_BTR;

然后创建变量:

_CAN_BTR *CAN_BTR = (_CAN_BTR*) &(CAN->BTR);

但是当使用以下代码编写时,我得到了错误的结果:

CAN_BTR->TS1 = 9;
CAN_BTR->TS2 = 4;
CAN_BTR->BRP = 6;
CAN_BTR->SJW = 3;

最后似乎在注册方面有问题,因为一切都很好,直到

strb    r3,[r2,#2]

其中 r3 保存正确值 r2 保存 CAN_BTR 寄存器的基地址和 #2 ossfet 指向保存 TS1 值的寄存器的第三个字节。

在对 asm 进行了一些实验后,我发现出于某种原因

strb    r3,#2]

总是修改该寄存器的第一个(偏移量 0)和第三个(偏移量 2)字节。使用局部变量就没有这样的问题。

CAN_BTR 默认值为 0x1230000 以及以下任何说明

strb    r3,#0]
strb    r3,#1]
strb    r3,#2]
strb    r3,#3]

它变成了0x1290129

是否有任何我不知道的硬件错误或限制?我检查了 STM32F407 的勘误表,但在 CAN 部分没有类似的东西。

提前感谢您的回答。

*更新

更多关于代码 - 反汇编列表:

 79       CAN_BTR->TS1 = 9;
080006da:   ldr     r2,[r7,#16]
080006dc:   ldrb    r3,#2]
080006de:   movs    r1,#9
080006e0:   bfi     r3,r1,#0,#4
080006e4:   strb    r3,#2]
 80       CAN_BTR->TS2 = 4;
080006e6:   ldr     r2,#16]
080006e8:   ldrb    r3,#2]
080006ea:   movs    r1,#4
080006ec:   bfi     r3,#4,#3
080006f0:   strb    r3,#2]
 81       CAN_BTR->BRP = 6;
080006f2:   ldr     r3,#16]
080006f4:   movs    r2,#0
080006f6:   orr.w   r2,r2,#6
080006fa:   strb    r2,[r3,#0]
080006fc:   ldrb    r2,#1]
080006fe:   bic.w   r2,#3
08000702:   strb    r2,#1]
 82       CAN_BTR->SJW = 3;
08000704:   ldr     r2,#16]
08000706:   ldrb    r3,#3]
08000708:   orr.w   r3,r3,#3
0800070c:   strb    r3,#3]

在第一行寄存器之前有默认值0x1230000。 在这一行之后

080006e4:   strb    r3,#2]

寄存器值为 0x1290129

我需要展示更多代码来说明我的问题吗?

*更新 2

现在类型定义为:

typedef struct
{
    union
    {
        struct
        {
            uint32_t BRP :10;
            uint32_t  :6;
            uint32_t TS1 :4;
            uint32_t TS2 :3;
            uint32_t  :1;
            uint32_t SJW :2;
            uint32_t  :4;
            uint32_t LBKM :1;
            uint32_t SILM :1;

        };
        uint32_t reg;
    };
} _CAN_BTR;

但这会导致相同的汇编代码:

 86       CAN_BTR->TS1 = 9;
08000718:   ldr     r2,#16]
0800071a:   ldrb    r3,#2]
0800071c:   movs    r1,#9
0800071e:   bfi     r3,#4
08000722:   strb    r3,#2]

*灵魂

由于 0___________ 的 pionetd 问题是以字节形式访问 CAN 寄存器,但参考手册只允许字(32 位)访问。谢谢!

解决方法

CAN 寄存器 HAVE 可作为字访问。您的代码以字节形式访问它们,这是 INVALID

不要引入指针,因为它会降低性能。

}__attribute__((packed,aligned(1))) _CAN_BTR;对齐没有意义。不需要打包,会发出非常低效的代码,还会强制无效的字节访问!!!

您不需要命名位域填充。

typedef struct
{
    union
    {
        struct
        {
            uint32_t BRP :10;
            uint32_t  :6;
            uint32_t TS1 :4;
            uint32_t TS2 :3;
            uint32_t  :1;
            uint32_t SJW :2;
            uint32_t  :4;
            uint32_t LBKM :1;
            uint32_t SILM :1;
        };
        uint32_t reg;
    };
}_CAN_BTR;
#define MYCAN_BTR ((volatile _CAN_BTR *)(&CAN -> BTR))

并在不引入任何开销的情况下访问位域。

MYCAN_BTR -> SJW = ....

更新如果您的编译器生成此代码,您需要以不同的方式进行。

#define MODIFY_CAN_BTR(field,val) do{_CAN_BTR btr = CAN->BTR; btr -> field = val; CAN -> BTR = btr -> reg;}while(0)

大佬总结

以上是大佬教程为你收集整理的STM32F407 在写入 CAN_BTR 寄存器时的奇怪行为全部内容,希望文章能够帮你解决STM32F407 在写入 CAN_BTR 寄存器时的奇怪行为所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。
标签: