赞
踩
本文会介绍oled的基本驱动,让其显示一些基础的东西,并且通过两个单片机来实现一个简单的pwm捕获功能(疫情原因没有信号发生,只能用一个单片机来执行输出)。先讲讲思路吧,我会先用一个单片机来输出一个稳定的pwm波,然后再对第二个单片机实现pwm波的捕获功能,最后连接oled模块实现数据的显示。在这里我使用的单片机为stm32rct6和stm32c6t6.
先是基本配置,打开时钟
然后stlink下载
然后是时钟树配置
下面两个是对应的设置,我就不细说了。
接着就是定时器的配置了,为了方便观察,我把我的单片机上的led对应的灯的io口,让其为pwm波的输出口。在这里我的led是pA8,所以我选择tim1和通道一,打开内部时钟。
接下来就是pwm波的数据配置,为了方便观察,我设定的为周期1s,占空比50%,数据如下
最后生成工程,打开keil,在这个位置打开就欧克了。
- /* USER CODE BEGIN 2 */
- HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_1);
- /* USER CODE END 2 */
首先cubemx还是老样子,在这里我只打开了tim2的channel4,用于捕获。对应的引脚配置根据自己的来就可以了,这里我的io口是PB11,在后面再说如何连接。
接下来就是代码编写,如下图位置,都已经做了注释
- /* USER CODE BEGIN PV */
- unsigned char capture_flag=0;//电平变化次数
- unsigned int capture_buf[3]= {0};
- //存时间数据的数组,分别为存第一次上升时间,第一次下降时间,和第二次上升时间
- double high_time=0;//存高电平时间
- double low_time=0;//存低电平时间
- double T=0;//周期
- double f=0;//频率
- double Duty=0;//占空比的值
- /*已经用cubemx设置PSC为72-1,ARR是1000,也就是1ms计数一次*/
- /* USER CODE END PV */
-
- /* USER CODE BEGIN PFP */
- void capture(void);//这里这个是一个函数声明,会用于下面的函数,到下面了再解析。
- /* USER CODE END PFP */
然后我们在这个区域块,编写捕获函数
- /* USER CODE BEGIN 4 */
- void capture()
- {
- switch(capture_flag)
- {
- case 0:
- capture_flag++;
- //flag变为1后回到tim.c的文件里面去执行捕获的内容
- __HAL_TIM_SET_CAPTUREPOLARITY(&htim2, TIM_CHANNEL_4, TIM_INPUTCHANNELPOLARITY_RISING);
- //检测到电平上升,开启上升沿捕获功能
- HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_4); //打开输入捕获
- break;
- case 4:
- high_time = capture_buf[1]- capture_buf[0];
- //高电平时间为第一次捕获下降沿的时间减去第一次上升沿的时闿
- low_time= capture_buf[2]- capture_buf[1];
- //低电平时间为第二次上升沿减去第一次下降沿的时闿
- capture_flag = 0; //使其为0
- break;
- default:
- break;
- }
- }
- /* USER CODE END 4 */
接着打开Tim.c文件,我们要在这里实现完整的捕获过程,先进行一些基本定义声明。
- /* USER CODE BEGIN 0 */
- extern unsigned char capture_flag;//设置全部的一个flag方便两个.c使用
- extern unsigned int capture_buf[3];//同理设置数组
- void capture_timer(void);//声明捕捉函敿
- //extern double T=0;//周期
- //extern double f=0;//频率
- //extern double Duty=0;//占空比
- void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)//执行的函敿
- {
- if(TIM2 == htim->Instance)
- {
- capture_timer();
- }
- }
- /* USER CODE END 0 */
然后我们拉到最下面,写入这段代码
- /* USER CODE BEGIN 1 */
- void capture_timer()
- {
- switch(capture_flag)//main里面出来的时候flag是1
- {
- case 1:
- {
- capture_buf[0] = HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_4);
- //获取第一次上升电平的时间并且存储在数组1里面
- __HAL_TIM_SET_CAPTUREPOLARITY(&htim2,TIM_CHANNEL_4,TIM_ICPOLARITY_FALLING);
- //把捕获设置为下降沿捕获
- capture_flag++;//flag变成2
- break;
- }
- case 2:
- {
- capture_buf[1] = HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_4);
- //获取第一次下降电平时间并且存储在数组2里面
- __HAL_TIM_SET_CAPTUREPOLARITY(&htim2,TIM_CHANNEL_4,TIM_ICPOLARITY_RISING);
- //再设为上升沿捕获来获取第二次上升
- capture_flag++;//flag变成3
- break;
- }
- case 3:
- {
- capture_buf[2] = HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_4);
- //获取第二次上升电平时间并且存储在数组三里靿
- HAL_TIM_IC_Stop_IT(&htim2,TIM_CHANNEL_4); //停止捕获
- capture_flag++;//变为4返回原先main里面的switch
- break;
- }
- }
- }
- /* USER CODE END 1 */
以上就是第二个单片机通过定时器实现的一个简单的pwm波的捕获,详细的内容大家可以看别的文章,在这里先大概说一下,其实就是打开一个定时器来计数,通过次数来计算时间的方式,最后存储到数组里面来实现数据捕获,详细的原理请大家去找别的博主,这里一定要先搞清楚定时器捕获的原理再进行编写。
接下来就是对oled驱动的重头戏了,其实oled驱动很简单,首先提醒大家在购买oled的时候尽量找商家要相关的驱动资料,我当初买的时候元旦放假,商家都休息了,我根本拿不到资料,最后是在网站上一个个找一个个试才成功的,相当浪费时间,有驱动文件真的真的会非常轻松!在这里我的oled是0.96寸的iic协议的。
然后考虑内容比较多,我会把四个文件放到别的地方去,使用的时候直接照搬就行了。
接下来就是cubemx的配置了,还是原先的地方,在这里只要打开iic就行了,同时注意sda和scl对应的io口
然后这里的I2C Speed Mode就是 IIC模式设置 ,主要为快速模式和标准模式。实际上也就是速率的选择。,这里我们是标准模式。I2C Clock Speed就是I2C的传输速率,默认为100KHz,基本上这里不需要改动什么,只要打开iic就行了。
接下来就是keil的代码编写
- /* USER CODE BEGIN Includes */
- #include "oled.h"
- #include "stdio.h"
- /* USER CODE END Includes */
- /* USER CODE BEGIN 1 */
- //在main的下面做如下定义
-
- //在前面定义变量
-
- float K1 = T;
- float K2 =Duty;
- float K3 = f;
- uint8_t K1_1[10];
- uint8_t K2_2[10];
- uint8_t K3_3[10];
- /* USER CODE END 1 */
显示的部分我们放在while循环里面
- OLED_Refresh();
- //这个refresh很重要,没有他你的显示基本是不正常的
-
- sprintf(K1_1, "fre:%.2f", K1);//输出频率
- sprintf(K2_2, "duty:%.4f", K2);//输出占空比
- sprintf(K3_3, "T:%.4f", K3);//输出周期
- OLED_ShowString(0,0,K1_1,16,1);//这个是oled驱动里面的,是显示位置的一个函数,
- OLED_ShowString(0,15,K2_2,16,1);//格式是(x轴,y轴,显示变量,16,1)
- 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的基本显示的话,取模的教程在网上还是比较多的,教程也非常详细,在这里我就只介绍变量之类的显示了。
那到这就结束了,谢谢各位。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。