当前位置:   article > 正文

使用stm32驱动oled的变量显示(IIC),以及对pwm的捕获实验(使用cubemx)

使用stm32驱动oled的变量显示(IIC),以及对pwm的捕获实验(使用cubemx)

本文会介绍oled的基本驱动,让其显示一些基础的东西,并且通过两个单片机来实现一个简单的pwm捕获功能(疫情原因没有信号发生,只能用一个单片机来执行输出)。先讲讲思路吧,我会先用一个单片机来输出一个稳定的pwm波,然后再对第二个单片机实现pwm波的捕获功能,最后连接oled模块实现数据的显示。在这里我使用的单片机为stm32rct6和stm32c6t6.

一、先对第一个单片机的cubemx进行配置

先是基本配置,打开时钟

 然后stlink下载

然后是时钟树配置

下面两个是对应的设置,我就不细说了。

接着就是定时器的配置了,为了方便观察,我把我的单片机上的led对应的灯的io口,让其为pwm波的输出口。在这里我的led是pA8,所以我选择tim1和通道一,打开内部时钟。

接下来就是pwm波的数据配置,为了方便观察,我设定的为周期1s,占空比50%,数据如下

 最后生成工程,打开keil,在这个位置打开就欧克了。

  1. /* USER CODE BEGIN 2 */
  2. HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_1);
  3. /* USER CODE END 2 */

 二、第二个单片机的捕获配置

首先cubemx还是老样子,在这里我只打开了tim2的channel4,用于捕获。对应的引脚配置根据自己的来就可以了,这里我的io口是PB11,在后面再说如何连接。

接下来就是代码编写,如下图位置,都已经做了注释

  1. /* USER CODE BEGIN PV */
  2. unsigned char capture_flag=0;//电平变化次数
  3. unsigned int capture_buf[3]= {0};
  4. //存时间数据的数组,分别为存第一次上升时间,第一次下降时间,和第二次上升时间
  5. double high_time=0;//存高电平时间
  6. double low_time=0;//存低电平时间
  7. double T=0;//周期
  8. double f=0;//频率
  9. double Duty=0;//占空比的值
  10. /*已经用cubemx设置PSC为72-1,ARR是1000,也就是1ms计数一次*/
  11. /* USER CODE END PV */
  12. /* USER CODE BEGIN PFP */
  13. void capture(void);//这里这个是一个函数声明,会用于下面的函数,到下面了再解析。
  14. /* USER CODE END PFP */

然后我们在这个区域块,编写捕获函数

  1. /* USER CODE BEGIN 4 */
  2. void capture()
  3. {
  4. switch(capture_flag)
  5. {
  6. case 0:
  7. capture_flag++;
  8. //flag变为1后回到tim.c的文件里面去执行捕获的内容
  9. __HAL_TIM_SET_CAPTUREPOLARITY(&htim2, TIM_CHANNEL_4, TIM_INPUTCHANNELPOLARITY_RISING);
  10. //检测到电平上升,开启上升沿捕获功能
  11. HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_4); //打开输入捕获
  12. break;
  13. case 4:
  14. high_time = capture_buf[1]- capture_buf[0];
  15. //高电平时间为第一次捕获下降沿的时间减去第一次上升沿的时闿
  16. low_time= capture_buf[2]- capture_buf[1];
  17. //低电平时间为第二次上升沿减去第一次下降沿的时闿
  18. capture_flag = 0; //使其为0
  19. break;
  20. default:
  21. break;
  22. }
  23. }
  24. /* USER CODE END 4 */

接着打开Tim.c文件,我们要在这里实现完整的捕获过程,先进行一些基本定义声明。

  1. /* USER CODE BEGIN 0 */
  2. extern unsigned char capture_flag;//设置全部的一个flag方便两个.c使用
  3. extern unsigned int capture_buf[3];//同理设置数组
  4. void capture_timer(void);//声明捕捉函敿
  5. //extern double T=0;//周期
  6. //extern double f=0;//频率
  7. //extern double Duty=0;//占空比
  8. void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)//执行的函敿
  9. {
  10. if(TIM2 == htim->Instance)
  11. {
  12. capture_timer();
  13. }
  14. }
  15. /* USER CODE END 0 */

然后我们拉到最下面,写入这段代码

  1. /* USER CODE BEGIN 1 */
  2. void capture_timer()
  3. {
  4. switch(capture_flag)//main里面出来的时候flag是1
  5. {
  6. case 1:
  7. {
  8. capture_buf[0] = HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_4);
  9. //获取第一次上升电平的时间并且存储在数组1里面
  10. __HAL_TIM_SET_CAPTUREPOLARITY(&htim2,TIM_CHANNEL_4,TIM_ICPOLARITY_FALLING);
  11. //把捕获设置为下降沿捕获
  12. capture_flag++;//flag变成2
  13. break;
  14. }
  15. case 2:
  16. {
  17. capture_buf[1] = HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_4);
  18. //获取第一次下降电平时间并且存储在数组2里面
  19. __HAL_TIM_SET_CAPTUREPOLARITY(&htim2,TIM_CHANNEL_4,TIM_ICPOLARITY_RISING);
  20. //再设为上升沿捕获来获取第二次上升
  21. capture_flag++;//flag变成3
  22. break;
  23. }
  24. case 3:
  25. {
  26. capture_buf[2] = HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_4);
  27. //获取第二次上升电平时间并且存储在数组三里靿
  28. HAL_TIM_IC_Stop_IT(&htim2,TIM_CHANNEL_4); //停止捕获
  29. capture_flag++;//变为4返回原先main里面的switch
  30. break;
  31. }
  32. }
  33. }
  34. /* USER CODE END 1 */

以上就是第二个单片机通过定时器实现的一个简单的pwm波的捕获,详细的内容大家可以看别的文章,在这里先大概说一下,其实就是打开一个定时器来计数,通过次数来计算时间的方式,最后存储到数组里面来实现数据捕获,详细的原理请大家去找别的博主,这里一定要先搞清楚定时器捕获的原理再进行编写。

三、对oled的基本驱动

接下来就是对oled驱动的重头戏了,其实oled驱动很简单,首先提醒大家在购买oled的时候尽量找商家要相关的驱动资料,我当初买的时候元旦放假,商家都休息了,我根本拿不到资料,最后是在网站上一个个找一个个试才成功的,相当浪费时间,有驱动文件真的真的会非常轻松!在这里我的oled是0.96寸的iic协议的。

 

然后考虑内容比较多,我会把四个文件放到别的地方去,使用的时候直接照搬就行了。

oled的驱动文件(原文的补充在这里)_ZHAOsir1118的博客-CSDN博客122https://blog.csdn.net/ZHAOsir1118/article/details/123013476?spm=1001.2014.3001.5502

然后是取模软件的下载,网上有很多,这里拿出一个我下的,取模也很简单,在这里我就不教学怎么使用了,网上的都教的很详细了https://blog.csdn.net/qq_43106548/article/details/119360520?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164520005116780271926529%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=164520005116780271926529&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-2-119360520.pc_search_result_cache&utm_term=pctolcd2002%E4%B8%8B%E8%BD%BD&spm=1018.2226.3001.4187https://blog.csdn.net/qq_43106548/article/details/119360520?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164520005116780271926529%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=164520005116780271926529&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-2-119360520.pc_search_result_cache&utm_term=pctolcd2002%E4%B8%8B%E8%BD%BD&spm=1018.2226.3001.4187

 接下来就是cubemx的配置了,还是原先的地方,在这里只要打开iic就行了,同时注意sda和scl对应的io口

然后这里的I2C Speed Mode就是 IIC模式设置 ,主要为快速模式和标准模式。实际上也就是速率的选择。,这里我们是标准模式。I2C Clock Speed就是I2C的传输速率,默认为100KHz,基本上这里不需要改动什么,只要打开iic就行了。

接下来就是keil的代码编写

  1. /* USER CODE BEGIN Includes */
  2. #include "oled.h"
  3. #include "stdio.h"
  4. /* USER CODE END Includes */
  1. /* USER CODE BEGIN 1 */
  2. //在main的下面做如下定义
  3. //在前面定义变量
  4. float K1 = T;
  5. float K2 =Duty;
  6. float K3 = f;
  7. uint8_t K1_1[10];
  8. uint8_t K2_2[10];
  9. uint8_t K3_3[10];
  10. /* USER CODE END 1 */

显示的部分我们放在while循环里面

  1. OLED_Refresh();
  2. //这个refresh很重要,没有他你的显示基本是不正常的
  3. sprintf(K1_1, "fre:%.2f", K1);//输出频率
  4. sprintf(K2_2, "duty:%.4f", K2);//输出占空比
  5. sprintf(K3_3, "T:%.4f", K3);//输出周期
  6. OLED_ShowString(0,0,K1_1,16,1);//这个是oled驱动里面的,是显示位置的一个函数,
  7. OLED_ShowString(0,15,K2_2,16,1);//格式是(x轴,y轴,显示变量,161
  8. OLED_ShowString(0,30,K3_3,16,1);//详细的可以查看驱动文件,不细说了,这些函数基本都是套用

然后代码的编写就欧克了。

四、实物连接和实验测试

首先是第一个单片机,我们定义的是PA8口的,并且周期1s,占空比50,然后led就会一闪一闪的,,说明单片机一输出了pwm波,然后我们再连接oled和第二个单片机,连接方式为vcc和gnd连接,然后oled的scl连接PB6,我的cubemx里面pb6为scl,然后oled的sda连接单片机的PB7,然后把keil烧录进去,reset下,就可以看到如下的照片

 然后我们这个时候要把第一个单片机输出pwm的io口,和第二个单片机的pwm波的接收io口连接,这里回应前面说的,在这里我的第一个单片机设置的是PA8输出,第二个设置的是PB11接收,那么把这两个对应的连接就ok了,同时要供地,再用一根杜邦线连接各自的gnd。经过测试,可以得到下面的图片

 可以看到误差还是可以接受的,(本人还是个小白,编写的东西可能不够完整,数据偏差还是比较大的,加上连接等等问题,还会出现很多不稳定的情况,照片里面的其实是比较稳定的时候了),然后本文只是简单介绍和使用了oled显示变量的功能(IIC),如果是oled的基本显示的话,取模的教程在网上还是比较多的,教程也非常详细,在这里我就只介绍变量之类的显示了。

那到这就结束了,谢谢各位。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/309479
推荐阅读
相关标签
  

闽ICP备14008679号