数码之家

 找回密码
 立即注册
搜索
查看: 4150|回复: 27

[STM] 关于stm8s的库函数和寄存器问题请教大家

[复制链接]
发表于 2021-8-28 12:34:25 | 显示全部楼层 |阅读模式

爱科技、爱创意、爱折腾、爱极致,我们都是技术控

您需要 登录 才可以下载或查看,没有账号?立即注册

x
库函数
#define OLED_SCLK_Clr()   GPIO_WriteLow(GPIOB, GPIO_PIN_4)
#define OLED_SCLK_Set()  GPIO_WriteHigh(GPIOB, GPIO_PIN_4)
#define OLED_SDIN_Clr()   GPIO_WriteLow(GPIOB, GPIO_PIN_5)
#define OLED_SDIN_Set()  GPIO_WriteHigh(GPIOB, GPIO_PIN_5)
寄存器
#define OLED_SCLK_Clr()   PB_ODR_bit.ODR4 = 0
#define OLED_SCLK_Set()  PB_ODR_bit.ODR4 = 1
#define OLED_SDIN_Clr()   PB_ODR_bit.ODR5 = 0
#define OLED_SDIN_Set()  PB_ODR_bit.ODR5 = 1


如上,宏定义这两个应该是等价的,一个是库函数操作,一个是直接操作寄存器,问题是上面的库函数正常显示,下面的寄存器就不行,编译不报错但是不显示,问题出在哪里百思不得其解
还请大神指教,谢谢

发表于 2021-8-28 13:01:23 | 显示全部楼层
寄存器操作不但定义电平,还要首先完成初始化(定义输入还是输出、高速还是低速、推动方式等)下面使用过的部分例子。
#define SCL PA_ODR_ODR1              //SPI时钟
#define SDA PA_ODR_ODR2       //SPI数据
/********IO口设置 初始化*******/
void IIC_Init()
{
    PA_DDR|=0X06;
    PA_CR1=0XFF;
    PA_CR2=0X00;
    PA_ODR|=0X06;
    }
/***********启动IIC ***********/
void start_IIC(void)
{
SCL=1;//给芯片发送开始信号
SDA=1;
IIC_delay();
SDA=0;
IIC_delay();
SCL=0;//开始信号传送完
IIC_delay();
}

可以参考一下。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-8-28 13:22:27 | 显示全部楼层
89609x 发表于 2021-8-28 13:01
寄存器操作不但定义电平,还要首先完成初始化(定义输入还是输出、高速还是低速、推动方式等)下面使用过的 ...

引脚初始化都是用的下面的寄存器版
void OLED_Init(void)
{
  PB_DDR_bit.DDR4 = 1;   //设置PB->4 为输出
  PB_CR1_bit.C14 = 1;    //设置为推挽输出
  PB_CR2_bit.C24 = 1;    //设置高速输出
  PB_ODR_bit.ODR4 = 0;  //设置低电平输出

  PB_DDR_bit.DDR5 = 1;   //设置PB->5 为输出
  PB_CR1_bit.C15 = 1;    //设置为推挽输出
  PB_CR2_bit.C25 = 1;    //设置高速输出
  PB_ODR_bit.ODR5 = 0;  //设置低电平输出
}

初始化当然必须有的啊,初始化用的都是这个 寄存器版,上面的那个用寄存器就不行,用库函数就行,意思就是 初始化代码是寄存器加 上面的库函数才能行,初始化寄存器加上面的寄存器 就不行
回复 支持 反对

使用道具 举报

发表于 2021-8-28 14:35:11 | 显示全部楼层
把库函数的原码拿出来看下就知道差别在哪, 不要光看函数名
回复 支持 反对

使用道具 举报

发表于 2021-8-28 14:50:05 | 显示全部楼层
宏定义可完全当做文本替换,遵循纯粹的先替换再计算的规则,LZ可以看下调用的地方是否被先计算了。
回复 支持 反对

使用道具 举报

发表于 2021-8-28 17:32:13 | 显示全部楼层
寄存器操作不是写个0或者1,需要初始化IO口,我都是直接操作寄存器的,怎么就没问题:doubt:
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-8-28 17:38:32 | 显示全部楼层
inthsunshine 发表于 2021-8-28 14:35
把库函数的原码拿出来看下就知道差别在哪, 不要光看函数名

你还没有明白我的意思,原本的库函数是stm8s.H中的, 我不想用这个h,现在用的是iostm8s103f3.h这个 先不管stm8h中的库函数源码是啥, 在103f3中的这个PB_ODR_bit.ODR4 = 0 应该是等同于GPIO_WriteLow(GPIOB, GPIO_PIN_4)这个吧。都是PB4输出低或者高,其他的都不动,就改这一句,用GPIO_WriteLow(GPIOB, GPIO_PIN_4)这个就能正常,用PB_ODR_bit.ODR4 = 0就不正常。我是这里搞不懂是什么情况,都是配置PB4低或者高。 初始化用PB_ODR_bit.ODR4 = 0就正常。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-8-28 17:45:26 | 显示全部楼层
89609x 发表于 2021-8-28 13:01
寄存器操作不但定义电平,还要首先完成初始化(定义输入还是输出、高速还是低速、推动方式等)下面使用过的 ...

你这种我也测试过,#define SCL PA_ODR_ODR1              //SPI时钟  SCL=0  也是不行,不宏定义,直接在函数中用 PA_ODR_ODR1=0都没有用,那两句只能用库函数才起作用,寄存器就不起作用,所以才觉得想不通
回复 支持 反对

使用道具 举报

发表于 2021-8-28 18:22:48 来自手机浏览器 | 显示全部楼层
8s的寄存器不是这个名字吧怎么感觉跟8L的一样…
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-8-28 18:23:19 | 显示全部楼层
89609x 发表于 2021-8-28 13:01
寄存器操作不但定义电平,还要首先完成初始化(定义输入还是输出、高速还是低速、推动方式等)下面使用过的 ...

为此还特意做了个实验
这样直接进去,库函数的就正常
void IIC_Start()
{

GPIO_WriteHigh(GPIOB, GPIO_PIN_4);
GPIO_WriteHigh(GPIOB, GPIO_PIN_5);

GPIO_WriteLow(GPIOB, GPIO_PIN_5);
GPIO_WriteLow(GPIOB, GPIO_PIN_4);

}

/**********************************************
//IIC Stop
**********************************************/
void IIC_Stop()
{
GPIO_WriteHigh(GPIOB, GPIO_PIN_4);
GPIO_WriteLow(GPIOB, GPIO_PIN_4);

GPIO_WriteLow(GPIOB, GPIO_PIN_5);
GPIO_WriteHigh(GPIOB, GPIO_PIN_5);

}

void IIC_Wait_Ack()
{
GPIO_WriteHigh(GPIOB, GPIO_PIN_4);
GPIO_WriteLow(GPIOB, GPIO_PIN_4);

}


然后 是这个寄存器的这样就不正常。
void IIC_Start()
{

PB_ODR_ODR4=1;
PB_ODR_ODR5=1;

PB_ODR_ODR5=0;
PB_ODR_ODR4=0;
}

/**********************************************
//IIC Stop
**********************************************/
void IIC_Stop()
{
PB_ODR_ODR4=1;
PB_ODR_ODR4=0;

PB_ODR_ODR5=0;
PB_ODR_ODR5=1;
}

void IIC_Wait_Ack()
{
PB_ODR_ODR4=1;
PB_ODR_ODR4=0

}
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-8-28 18:24:08 | 显示全部楼层
触景情伤 发表于 2021-8-28 18:22
8s的寄存器不是这个名字吧怎么感觉跟8L的一样…

是这个呀,8s  8l都是一样的
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-8-28 19:50:48 | 显示全部楼层
inthsunshine 发表于 2021-8-28 14:35
把库函数的原码拿出来看下就知道差别在哪, 不要光看函数名

发现新情况  引脚换成PA1 PA2,使用寄存器如下也正常,说明代码也没有错。
#define OLED_SCLK_Clr()   PA_ODR_bit.ODR1 = 0

然后查了下PB4 PB5不能输出高电平 但是使用库函数 GPIO_WriteHigh(GPIOB, GPIO_PIN_4) 确能显示正常,先不管他高不高电平,显示就正常,这里有点费解,难道库函数还能把硬件不能输出高电平的脚输出高电平了?
回复 支持 反对

使用道具 举报

发表于 2021-8-28 20:36:38 | 显示全部楼层
本帖最后由 inthsunshine 于 2021-8-28 20:39 编辑
1588858 发表于 2021-8-28 17:38
你还没有明白我的意思,原本的库函数是stm8s.H中的, 我不想用这个h,现在用的是iostm8s103f3.h这个 先不 ...

为什么会“应该是等同于", 这只是你的猜测, 未必是事实,

究竟是不是,看下库函数源码不就有答案了吗?  为什么死活不肯去看下人家是怎么实现的呢? 否则早就知道答案

实际上看源码也是学习编程的一个途径,人家官方都是规范操作和书写
还好你没玩stm32,  32里面定时器的好几个库函数,看名字完全不同的函数,实际操作同一个寄存器的同样几个位, 只不过不同的取值而已,不看源码根本会混淆
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-8-28 21:07:04 | 显示全部楼层
inthsunshine 发表于 2021-8-28 20:36
为什么会“应该是等同于", 这只是你的猜测, 未必是事实,

究竟是不是,看下库函数源码不就有答案了吗?  ...

#define OLED_SCLK_Clr()   PB_ODR_bit.ODR4 = 0
是可以用的,用在其他脚上可以 0 1控制输出低和高,在PB4 5上就是不行。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-8-28 21:13:20 | 显示全部楼层
inthsunshine 发表于 2021-8-28 20:36
为什么会“应该是等同于", 这只是你的猜测, 未必是事实,

究竟是不是,看下库函数源码不就有答案了吗?  ...

你最终还是没有明白我说的是啥意思,费解。
PA_ODR_bit.ODR1 = 0
PA_ODR_bit.ODR2 = 1   这样是可以正常控制PA1

PB_ODR_bit.ODR4 = 0
PB_ODR_bit.ODR4 = 1   这样也可以正常控制PB4

但是在  GPIO_WriteLow(GPIOB, GPIO_PIN_4) 替换成 PB_ODR_bit.ODR4 = 0 就不能正常显示
          引脚换成PA1 然后用 PA_ODR_bit.ODR1 = 0 就能正常显示

回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-8-28 21:30:00 | 显示全部楼层
inthsunshine 发表于 2021-8-28 20:36
为什么会“应该是等同于", 这只是你的猜测, 未必是事实,

究竟是不是,看下库函数源码不就有答案了吗?  ...

而且 那个对应的库函数中的源码也试过的
源码是 低 GPIOx->ODR &= (uint8_t)(~PortPins)
          高 GPIOx->ODR |= (uint8_t)PortPins
然后直接这样 也是不显示  所以才发帖说百思不得其解
#define OLED_SCLK_Clr()   (GPIOB->ODR &= (uint8_t)(~GPIO_PIN_4))
#define OLED_SCLK_Set()   (GPIOB->ODR |= (uint8_t)GPIO_PIN_4)

#define OLED_SDIN_Clr()  (GPIOB->ODR &= (uint8_t)(~GPIO_PIN_5))
#define OLED_SDIN_Set()  (GPIOB->ODR |= (uint8_t)GPIO_PIN_5)
回复 支持 反对

使用道具 举报

发表于 2021-8-29 08:42:15 | 显示全部楼层
没有记错的话,PB4、5 是 IIC 引脚,开漏,与VDD 没有连接,只拉低和释放. 实际使用要接上拉。

回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-8-29 11:36:45 | 显示全部楼层
junyee 发表于 2021-8-29 08:42
没有记错的话,PB4、5 是 IIC 引脚,开漏,与VDD 没有连接,只拉低和释放. 实际使用要接上拉。

...

原理是这样的 所以换成PA1 PA2可以用PA_ODR_bit.ODR1 = 0 正常显示
但是PB4 PB5 用 GPIO_WriteLow(GPIOB, GPIO_PIN_4) 就能正常显示 问题就是这里搞不懂为什么用库函数能把不能输出推挽的PB4 PB5能给正常显示了IIC?
电路都是没有动,没有上拉的情况下测试的
而且上面的函数源码是  (GPIOB->ODR &= (uint8_t)(~GPIO_PIN_4)) 这样的,用这直接使用也是不显示
所以才觉得奇怪。
回复 支持 反对

使用道具 举报

发表于 2021-8-29 23:16:03 来自手机浏览器 | 显示全部楼层
你那个宏定义后面用大括号,里面=0结束分号,这样绝对ok,亲身经历
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-8-30 11:56:50 | 显示全部楼层
mckk520 发表于 2021-8-29 23:16
你那个宏定义后面用大括号,里面=0结束分号,这样绝对ok,亲身经历

试过任何方式,去掉括号 加上括号,包括不用宏定义,直接带入寄存器代码 就是不行,只能用这句库函数,但是用led灯测试单独pb4 pb5 不管哪一句代码都是有效控制,, 但是加在这里显示的话只能用那句库函数才能显示,所以才觉得奇怪。不然就没有发帖的意义了
回复 支持 反对

使用道具 举报

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

本版积分规则

APP|手机版|小黑屋|关于我们|联系我们|法律条款|技术知识分享平台

闽公网安备35020502000485号

闽ICP备2021002735号-2

GMT+8, 2025-5-11 05:03 , Processed in 0.171600 second(s), 12 queries , Redis On.

Powered by Discuz!

© 2006-2025 MyDigit.Net

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