大佬教程收集整理的这篇文章主要介绍了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,请注明来意。