小蜜蜂老师32cubemx学习笔记,对一些实验过程中可能出现的情况做出解释,对老师做补充,重复性工作ctrl+c/v使用,前期略显粗糙,后续随时更新,有错误感谢指正,根据自己板子的情况对视频中的程序做了调整,比如实在懒得加第二个LED灯~还有手头没有光敏,但有一个土壤湿度~很多地方写了注释,说不定你不明白的地方就写在注释里面~
这个是参考视频的链接,感谢这位UP我才能学的这么快😄点击即可:小蜜蜂老师B站课程链接 编译一下就有那个打开折叠的加号了~
有IT就对应中断,就要设置NVIC使能,就有回调函数,满足对应条件就会触发回调函数,中断的思维很重要~ 要注意你的板载LED灯是不是低电平才亮,接的单片机的哪个引脚捏~ 不得不说这软件真的好好用啊~ 回调函数里不要用HAL_Delay()
一、外部中断
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance==TIM2)
{
HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13);
}
if(htim->Instance==TIM3)
{
HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13);
}
}
初始化部分:
HAL_TIM_Base_Start_IT(&htim2);
原型:
HAL_StatusTypeDef HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *htim);
二、串口
有的串口助手没有显示文本功能,所以没办法显示中文(中文是乱码,改成同义的英文即可)。 定义与宏:
uint8_t Tx_str1[]="Hello,world!\r\n";
uint8_t Tx_str2[]="LED1_Open!\r\n";
uint8_t Tx_str3[]="LED1_Close!\r\n";
#define LED1_ON() HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,1);
串口接收中断回调函数:
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance==USART2)
{
if(Rx_dat==0xa1)
{
LED1_ON();
LED2_OFF();
HAL_UART_Transmit(&huart2,Tx_str1,sizeof(Tx_str1),10000);
LED2_OFF();
HAL_UART_Receive_IT(&huart2,&Rx_dat,1);
}
else if(Rx_dat==0xa2)
{
LED1_OFF();
LED2_ON();
HAL_UART_Transmit(&huart2,Tx_str1,sizeof(Tx_str1),10000);
LED2_OFF();
HAL_UART_Receive_IT(&huart2,&Rx_dat,1);
}
}
}
初始化部分:
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_SET);
HAL_UART_Transmit(&huart2,Tx_str1,sizeof(Tx_str1),10000);
HAL_UART_Receive_IT(&huart2,&Rx_dat,1);
三、定时器串口混合应用
在cubemx里面把预分频器与主计数器设置好数值~ 手动引入新的头文件、定义与宏,位置:BEGIN0:
#include "stdio.h"
#define LED_on() HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_RESET)
#define LED_off() HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_SET)
#define LED_invert() HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13)
uint8_t str1[]="==============Hello!================\r\n";
uint8_t hh=0,mm=0,ss=0,ss05=0;
uint8_t str_buff[64];
uint8_t Rx_dat[16];
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance==TIM2)
{
HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13);
ss05++;
if(ss05==2)
{
ss05=0;
ss++;
if(ss==60)
{
ss=0;
mm++;
if(mm==60)
{
mm=0;
hh++;
}
}
}
}
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance==USART2)
{
if(Rx_dat[0]==0xBF&&Rx_dat[2]==0xFB)
{
switch(Rx_dat[1])
{
case 0xa1:
sprintf((char *)str_buff,"%d:%d:%d LED open!\r\n",hh,mm,ss);
break;
case 0xa2:
sprintf((char *)str_buff,"%d:%d:%d LED close!\r\n",hh,mm,ss);
break;
default:
sprintf((char *)str_buff,"%d:%d:%d This is an error!\r\n",hh,mm,ss);
break;
}
HAL_UART_Transmit(&huart2,str_buff,sizeof(str_buff),10000);
HAL_UART_Receive_IT(&huart2,Rx_dat,3);
}
}
}
if(ss05==2),当时设置的是500ms中断一次,所以中断两次秒才能加一 初始化,位置:BEGIN2:
HAL_UART_Transmit(&huart2,str1,sizeof(str1),10000);
HAL_TIM_Base_Start_IT(&htim2);
HAL_UART_Receive_IT(&huart2,Rx_dat,3);
感觉在循环中写电平翻转有点问题??
四、数模转换
若是查询式
#include "stdio.h"
#define LED1_ON() HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_RESET)
#define LED1_OFF() HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_SET)
uint8_t str1[]="==============Hello!================\r\n";
uint16_t ADC_Val = 0,ADC_Volt=0;
uint8_t str_buff[44];
void UART1_Send_Info()
{
sprintf((char *)str_buff,"Sample_Val:%d,Volt_Val:%d.%d%dV\r\n",ADC_Val,ADC_Volt/100,(ADC_Volt%100)/10,ADC_Volt%10);
HAL_UART_Transmit(&huart1,str_buff,sizeof(str_buff),10000);
}
void ADC0_Get_Val()
{
HAL_ADC_Start(&hadc1);
LED1_ON();
if(HAL_ADC_PollForConversion(&hadc1,10) == HAL_OK)
{
ADC_Val = HAL_ADC_GetValue(&hadc1);
ADC_Volt = ADC_Val*330/4096;
}
UART1_Send_Info();
LED1_OFF();
HAL_ADC_Stop(&hadc1);
}
————————————————初始化——————————————————————
HAL_UART_Transmit(&huart1,str1,sizeof(str1),10000);
————————————————主循环——————————————————————
ADC0_Get_Val();
HAL_Delay(500);
若是中断式
#include "stdio.h"
#define LED1_ON() HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_RESET)
#define LED1_OFF() HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_SET)
uint8_t str1[]="==============Are you ok?================\r\n";
uint16_t ADC_Val = 0,ADC_Volt=0;
uint8_t str_buff[44];
void UART1_Send_Info()
{
sprintf((char *)str_buff,"Sample_Val:%d,Volt_Val:%d.%d%dV\r\n",ADC_Val,ADC_Volt/100,(ADC_Volt%100)/10,ADC_Volt%10);
HAL_UART_Transmit(&huart1,str_buff,sizeof(str_buff),10000);
}
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
if(hadc->Instance == ADC1)
{
ADC_Val = HAL_ADC_GetValue(&hadc1);
ADC_Volt = ADC_Val*330/4096;
UART1_Send_Info();
LED1_OFF();
}
}
————————————————————————————begin2——————————————————————————
HAL_UART_Transmit(&huart1,str1,sizeof(str1),10000);
————————————————————————————主循环————————————————————————————
LED1_ON();
HAL_ADC_Start_IT(&hadc1);
HAL_Delay(500);
ADC_Volt = ADC_Val*330/4096; 这句话里的4096是212得来的,12位的AD嘛不是,330是3.3V乘100得来的,3.3是参考电压,也是我们插上STlinkV2给板子的输入电压,为什么乘100呢?因为在下面这个句子里,为了让输出的电压单位为V,就不得不用小数去表示电压,为了不让测得的电压显示时损失太多精度,先乘了100后边又除以了一个100,保证了两位小数的电压实际值输出。 sprintf((char *)str_buff,“Sample_Val:%d,Volt_Val:%d.%d%dV\r\n”,ADC_Val,ADC_Volt/100,(ADC_Volt%100)/10,ADC_Volt%10); 好像说的不是很明白。。。。后续再说
五、OLED(SPI)
四脚的是IIC的,七脚的是SPI的,两者差别很大,视频用的后者~ 小蜜蜂老师整理的OLED资料与函数讲解 注意:RES脚要接到开发板的RESET脚上(每个板子应该都有的,引出来现成的),这样当你按下32的手动reset按钮时,也会给OLED屏幕复位,这个脚接不好屏幕直接不工作,不是连一个按钮接地这么简单(当时找错误找了好久好久)。
#include "XMF_OLED_STM32Cube.h"
extern unsigned char BMP1[];
void OLED_display_pic()
{
OLED_Clear();
OLED_DrawBMP(0,0,128,7,BMP1);
}
void OLED_display_info()
{
OLED_Clear();
OLED_ShowString(16,0,(uint8_t *)"Hello,World!");
OLED_ShowCHinese(10,3,0);
OLED_ShowCHinese(28,3,1);
OLED_ShowCHinese(46,3,2);
OLED_ShowCHinese(64,3,3);
OLED_ShowCHinese(82,3,4);
}
OLED_Init();
OLED_display_pic();
HAL_Delay(500);
OLED_display_info();
OLED_Init();别忘了初始化 OLED_ShowCHinese(82,3,4);最后一位4是指汉字库(HZK)里的第四个字~ 看好了他拼的有点奇怪,不是Chinese而是CHinese~
六、OLED+AD
#include "stdio.h"
#define LED_ON() HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_RESET)
#define LED_OFF() HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_SET)
extern unsigned char BMP1[];
uint16_t ADC_val=0,ADC_volt=0;
uint8_t str_buff[64];
void led_check()
{
LED_ON();
HAL_Delay(300);
LED_OFF();
HAL_Delay(300);
}
void oled_display_pic()
{
OLED_Clear();
OLED_DrawBMP(0,0,128,8,BMP1);
}
void oled_display_info()
{
OLED_Clear();
OLED_ShowString(0,0,(uint8_t *)"Blog of Z_0_0");
OLED_ShowCHinese(0,3,3);
OLED_ShowCHinese(18,3,4);
OLED_ShowCHinese(36,3,8);
OLED_ShowString(54,3,(uint8_t *)":");
OLED_ShowCHinese(0,5,0);
OLED_ShowCHinese(18,5,1);
OLED_ShowCHinese(36,5,8);
OLED_ShowString(54,5,(uint8_t *)":");
OLED_ShowString(100,5,(uint8_t *)"V");
}
void oled_display_data()
{
sprintf((char *)str_buff,"%d",ADC_val);
OLED_ShowString(64,3,str_buff);
sprintf((char *)str_buff,"%d.%d%d",ADC_volt/100,(ADC_volt%100)/10,ADC_volt%10);
OLED_ShowString(64,5,str_buff);
}
void GET_adc_val()
{
HAL_ADC_Start(&hadc1);
if(HAL_ADC_PollForConversion(&hadc1,10)== HAL_OK)
{
ADC_val=HAL_ADC_GetValue(&hadc1);
ADC_volt=ADC_val*330/4096;
oled_display_data();
}
if(ADC_volt<200)
{
LED_ON();
}
else
{
LED_OFF();
}
}
OLED_Init();
oled_display_pic();
oled_display_info();
while (1)
{
GET_adc_val();
HAL_Delay(300);
土壤湿度传感器与沾水的卫生纸配合使用~ 电压值最大是3.3V肯定 把土壤湿度传感器摁在湿润的卫生纸上~
使用%d输出时,上一次采样到的模拟值有四位数字这次采样是三位的话,如上一次3978,这次采样得到465,屏幕上会显示4658,这个多出来的8是由于上次3978第四位的8还留在屏幕上没有刷新掉,换成%4d三位数字实际上是465加一个空格,这样把上一次采样第四位8给挤掉了,显示就正常了。
实际上就是显示的问题,数字采样没错误,不用屏幕输出的情况完全不用考虑这个BUG。 测试%d与%4d的区别,%d是按照原型输出,有多少位就有多少位,另外c语言中数据的宽度是从右边开始算起的,比如%4d就表示数据宽度为4,不够的那空格来补,如果超出四位,则应该原型输出。具体测试程序如下,只需粘贴复制到VC6.0上运行就可知道两者的区别。 该段出自:%4d与%d讲解
本文后续再更新~感谢大家支持!
|