OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4169|回复: 6

求教!疑似Keil的bug?宏定义修改寄存器失效

[复制链接]

0

主题

6

帖子

0

精华

新手上路

积分
39
金钱
39
注册时间
2019-11-14
在线时间
9 小时
发表于 2022-3-27 14:44:39 | 显示全部楼层 |阅读模式
10金钱
本帖最后由 xjn666 于 2022-3-27 14:46 编辑

楼主是想用模拟IIC来驱动oled,由于觉得使用HAL库写引脚太慢,所以想通过直接写寄存器的方式去控制引脚。我的硬件配置是B8控制SCL,B9控制SDA。
最奇怪的地方就是:
(1)如果我的宏定义写的是以下,那么是可以控制oled的
  1. #define OLED_SCLK_Clr my_sclk_clr()
复制代码
其中这几个函数的定义是
  1. void my_sclk_clr(void) { GPIOB->BSRR = (uint32_t)GPIO_PIN_8 << 16u;}
  2. void my_sclk_set(void) { GPIOB->BSRR = GPIO_PIN_8;}
  3. void my_sdin_clr(void) { GPIOB->BSRR = (uint32_t)GPIO_PIN_9 << 16u;}
  4. void my_sdin_set(void) { GPIOB->BSRR = GPIO_PIN_9;}
复制代码
(2)而如果直接把修改寄存器放在宏定义中(如下),那么则无法控制oled
  1. #define OLED_SCLK_Clr  { GPIOB->BSRR = (uint32_t)GPIO_PIN_8 << 16u;}
  2. #define OLED_SCLK_Set  { GPIOB->BSRR = GPIO_PIN_8;}
  3. #define OLED_SDIN_Clr  { GPIOB->BSRR = (uint32_t)GPIO_PIN_9 << 16u;}
  4. #define OLED_SDIN_Set  { GPIOB->BSRR = GPIO_PIN_9;}
复制代码


附上我的模拟IIC代码,供大家查阅:
  1. //起始信号
  2. void oled096_I2C_Start(void)
  3. {
  4.      OLED_SDIN_Set;
  5.      OLED_SCLK_Set;
  6.      OLED_SDIN_Clr;
  7.      OLED_SCLK_Clr;
  8. }

  9. //结束信号
  10. void oled096_I2C_Stop(void)
  11. {
  12.      OLED_SCLK_Set;
  13.      OLED_SDIN_Clr;
  14.      OLED_SDIN_Set;
  15. }

  16. //等待信号响应
  17. void oled096_I2C_WaitAck(void) //测数据信号的电平
  18. {
  19.      OLED_SCLK_Set;
  20.      OLED_SCLK_Clr;
  21. }
复制代码







正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

0

主题

6

帖子

0

精华

新手上路

积分
39
金钱
39
注册时间
2019-11-14
在线时间
9 小时
 楼主| 发表于 2022-3-27 14:48:38 | 显示全部楼层
论坛发布有bug,能驱动oled的那个宏定义应该是如下,论坛给我吞了
  1. #define OLED_SCLK_Clr my_sclk_clr()
  2. #define OLED_SCLK_Set my_sclk_set()
  3. #define OLED_SDIN_Clr my_sdin_clr()
  4. #define OLED_SDIN_Set my_sdin_set()
复制代码
回复

使用道具 举报

0

主题

6

帖子

0

精华

新手上路

积分
39
金钱
39
注册时间
2019-11-14
在线时间
9 小时
 楼主| 发表于 2022-3-27 18:06:50 | 显示全部楼层
发现我的发送字节的模拟IIC的函数也被吞了,再发一次
  1. //发送一个字节
  2. void oled096_Send_Byte(u8 dat)
  3. {
  4.         u8 i;
  5.         for(i=0;i<8;i++)
  6.         {
  7.                 OLED_SCLK_Clr;//将时钟信号设置为低电平
  8.                 if(dat&0x80)//将dat的8位从最高位依次写入
  9.                 {
  10.                         OLED_SDIN_Set;
  11.     }
  12.                 else
  13.                 {
  14.                         OLED_SDIN_Clr;
  15.     }
  16.                 OLED_SCLK_Set;//将时钟信号设置为高电平
  17.                 OLED_SCLK_Clr;//将时钟信号设置为低电平
  18.                 dat<<=1;
  19.   }
  20. }
复制代码
回复

使用道具 举报

6

主题

34

帖子

0

精华

初级会员

Rank: 2

积分
119
金钱
119
注册时间
2019-2-12
在线时间
28 小时
发表于 2022-4-7 09:49:21 | 显示全部楼层
定义成宏函数如#define OLED_SCLK_Clr()  { GPIOB->BSRR = (uint32_t)GPIO_PIN_8 << 16u;};调用的时候也加上括号。你那种定义方式是常量,只执行一次的
回复

使用道具 举报

3

主题

805

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3833
金钱
3833
注册时间
2017-3-7
在线时间
1672 小时
发表于 2022-4-7 11:30:12 | 显示全部楼层
turelon 发表于 2022-4-7 09:49
定义成宏函数如#define OLED_SCLK_Clr()  { GPIOB->BSRR = (uint32_t)GPIO_PIN_8

这么写应该没问题,我试了下gcc下,加不加括号 对于参数为空的宏是没区别的,带参必须带()
回复

使用道具 举报

0

主题

6

帖子

0

精华

新手上路

积分
39
金钱
39
注册时间
2019-11-14
在线时间
9 小时
 楼主| 发表于 2022-4-7 21:46:48 | 显示全部楼层
a5820736 发表于 2022-4-7 11:30
这么写应该没问题,我试了下gcc下,加不加括号 对于参数为空的宏是没区别的,带参必须带()

请问“这么写”是指哪种写法呢?
回复

使用道具 举报

0

主题

6

帖子

0

精华

新手上路

积分
39
金钱
39
注册时间
2019-11-14
在线时间
9 小时
 楼主| 发表于 2022-4-7 21:47:45 | 显示全部楼层
turelon 发表于 2022-4-7 09:49
定义成宏函数如#define OLED_SCLK_Clr()  { GPIOB->BSRR = (uint32_t)GPIO_PIN_8

我的宏定义没有带参数,应该是不需要括号的呀
回复

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-2-27 14:31

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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