IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> STM32+CubeMX+Keil+HAL库 -> 正文阅读

[嵌入式]STM32+CubeMX+Keil+HAL库

?

目录

1. 设置GPIO:

?2. printf重定向

3. Log信息格式

4.?个性化输出

5. CubeMX+HAL打开串口中断

?6.?打开外部中断

7.?时钟树基本操作

8.?通用定时器配置

9. CubeMX配置定时器

(1)将定时器的时钟设为72M

?(2)选择内部时钟

?(3)配置定时器

?(4)开启中断

?定时器中断回调函数:(平滑滤波)

10.?CubeMX配置pwm

11.?CubeMX配置spwm

12.?CubeMX配置ADC

(1)轮询

(2)DMA方式

13. IIC和SPI


STM32系列视频(CubeMX+MDK5+HAL库+库函数一站式学习)_哔哩哔哩_bilibili

1. 设置GPIO:

(1)将PA8设置为输出,推挽上拉,初始状态为高电平:

?(2)使用pin?configuration里边的User Label,可以生成对应的宏,提高代码的复用性,并且方便移植。

?在对应的工程代码里就会有如下所示的宏定义:

?2. printf重定向

int fputc(int ch, FILE *f)
{
	uint8_t temp[1] = {ch};
	HAL_UART_Transmit(&huart1, temp, 1, 2);
	return ch;
}

3. Log信息格式

参考目前主流嵌入式、安卓等输出方式:

[日志级别] 文件名 : 日志信息
//例: [info] main.c : init ok!
//例: [debug] adc.c : adc_getvalue -> 3.3v

(1)可以使用条件编译的方式来决定是否打印Log信息:

#define Log   1  //不想打印时改为 0 即可


#if Log
printf("[info]main.c:init!\r\n");
#endif

(2)可变参数宏

#define USER_MAIN_DEBUG


#ifdef USER_MAIN_DEBUG


#define user_main_printf(format, ...) printf( format "\r\n",##__VA_ARGS__)

#define user_main_info(format, ...) printf("【main】info:" format "\r\n",##__VA_ARGS__)

#define user_main_debug(format, ...) printf("【main】debug:" format "\r\n",##__VA_ARGS__)

#define user_main_error(format, ...) printf("【main】error:" format "\r\n",##__VA_ARGS__)

#else

#define user_main_printf(format, ...)

#define user_main_info(format, ...) 

#define user_main_debug(format, ...)

#define user_main_error(format, ...)

#endif

当我需要打印串口信息时,define一个USER_MAIN_DEBUG,在我不需要时就将其注释。

4.?个性化输出

可以借助这个网站来设计字符:http://patorjk.com/software/taag/

printf(".__           .__  .__                            .__       .___");
printf("|  |__   ____ |  | |  |   ______  _  _____________|  |    __| _/");
printf("|  |  \\_/ __ \\|  | |  |  /  _ \\ \\/ \\/ /  _ _  __ \\  |   / __ | ");
printf("|   Y  \\  ___/|  |_|  |_(  <_> )     (  <_> )  | \\/  |__/ /_/ | ");
printf("|___|  /\\___  >____/____/\\____/ \\/\\_/ \\____/|__|  |____/\\____ |");
printf("     \\/     \\/                                               \\/");

5. CubeMX+HAL打开串口中断

?

?6.?打开外部中断

另外,EXTI外部中断的GPIO配置如下:默认下拉,上升沿触发。

然后编写外部中断的回调函数即可。

eg:测量pwm的频率

1s的时间内,上升沿的次数就是频率。也就是说,1s内进入外部中断的次数就是频率。每进一次中断,pwm_value加1,1s后它的值就是频率。

当有上升沿时,就进入外部中断将pwm_value的值加1。

int pwm_value = 0;

int main()
{
    pwm_value = 0;
    HAL_Delay(1000);   # 延时1s后得到的pwm_value就是频率值
    printf("[\tmain]info:pwm_value = %d\r\n", pwm_value);
}

# 外部中断的回调函数
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    if(GPIO_Pin == PWM_Pin)     # 判断触发的引脚是否是定义的引脚   
    {
        pwm_value++;
    }
}

7.?时钟树基本操作

(1)使能外部时钟源

一般情况下,生成的工程默认用的是内部时钟,所以先进行外部时钟的使能。

?(2)然后将HCLK时钟频率调到最大,例如f103最大是72M,而f406最大是84M。

?(3)最后,针对不同的外设进行按需分频。

8.?通用定时器配置

eg:特定时间翻转LED。

# 溢出时间
Tout = (arr+1)*(psc+1)/Tclk
频率:Tclk/(psc+1) MHz

void Timer3_Init(uint16_t arr,uint16_t psc)
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    NVIC_InitTypeDef  NVIC_InitStructure;	

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能

	TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值	 计数到5000为500ms
	TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值  10Khz的计数频率  
	TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
	TIM_ITConfig(TIM3,TIM_IT_Update|TIM_IT_Trigger,ENABLE);   //定时器中断使能

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);	//设置NVIC中断分组2:2位抢占优先级,2位响应优先级
    NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  //TIM3中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;  //先占优先级1级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;  //从优先级3级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
	NVIC_Init(&NVIC_InitStructure);  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器

	TIM_Cmd(TIM3, ENABLE);  //使能TIMx外设					 
}

void TIM3_IRQHandler(void)   //TIM3中断
{
    static uint8_t cnt = 0;    //静态变量
	if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM 中断源 
    {
        /*中断操作*/
        cnt++;
		TIM_ClearITPendingBit(TIM3, TIM_IT_Update  );  //清除TIMx的中断待处理位:TIM 中断源 
	}
    if(cnt == 10)
    {
        LED = ~LED;
        cnt = 0;
    }
}

9. CubeMX配置定时器

(1)将定时器的时钟设为72M

?(2)选择内部时钟

?(3)配置定时器

主要配置:定时时间,以及是否重装定时器。

定时频率 =?定时器时钟/(预分频 + 1)/(计数值 + 1)Hz。

定时时间 = 1/定时频率? s。

?(4)开启中断

基本定时器:

高级定时器:

?定时器中断回调函数:(平滑滤波)

eg:平滑滤波 -- 让采样值在另一个“线程”一直滤波,而在需要它的时候,直接取它的值即可。

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if(htim->Instance == htim1.Instance)
    {
        pwm_sum += pwm_value * 10;  //pwm_sum累加
        pwm_sum -= pwm_avg;         //pwm_sum减去上次的平均值
        pwm_avg = pwm_sum * 1.0 / 5; //更新pwm的平均值
        pwm_value_final = pwm_avg;   //pwm_value_final的值即为当前pwm的频率
        pwm_value = 0;               //将pwm_value清空,重新计数
    }
}

10.?CubeMX配置pwm

(1)使能PWM通道

?这里,将TIM2的Channel1设置为PWM输出通道。

(PWM Generation CHx 正向、PWM Generation CHxN 反向、 PWM Generation CHx CHxN 一对互补 pwm 输出)

(2)配置频率及占空比

频率 =?定时器时钟 / (Prescaler + 1) / (Cound Period + 1) Hz

占空比 = Pulse(对比值) / (Cound Period 计数值) %

?(3)下属代码实现了pwm占空比逐渐增大至1,然后变为0的一个过程。

int main(void)
{
    int pwm = 0;
  
    HAL_Init();

  /* Configure the system clock */
    SystemClock_Config();

  /* Initialize all configured peripherals */
    MX_GPIO_Init();
    MX_TIM1_Init();

    # 使能tim1的通道1
    HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);

    while (1)
    {
        HAL_Delay(5);
        # 修改tim1的通道1的pwm比较值为pwm++,即修改占空比
        __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, pwm++);
        pwm = (pwm > 999) ? 0:pwm;
    }
}

11.?CubeMX配置spwm

SPWM就是在PWM的基础上,让PWM的占空比做正弦变化。

STM32系列视频(CubeMX+MDK5+HAL库+库函数一站式学习)_哔哩哔哩_bilibili

略。

12.?CubeMX配置ADC

通常是12位,精度为3.3/4096?v。

读取ADC的方式:轮询、DMA。

(1)轮询

首先配置ADC1的CH0,并且使能连续采集。

while(1)
{
    HAL_ADC_Start(&hadc1);//启动ADC装换
    HAL_ADC_PollForConversion(&hadc1, 50);//等待转换完成, 第二个参数表示超时时间,单位ms.
    if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1), HAL_ADC_STATE_REG_EOC))
    { 
        AD_Value = HAL_ADC_GetValue(&hadc1);//读取ADC转换数据, 数据为12位
        printf("[\tmain]info:v=%.1fmv\r\n",AD_Value*3300.0/4096);//打印日志
    }
}

(2)DMA方式

①?初始化两个ADC通道

?②?配置

使能连续转换模式(Continuous Conversion Mode);

ADC规则组选择转换通道数为2(Number Of Conversion);

配置Rank的输入通道,分别转换channel 0和channel 1。

③?添加DMA

设置为连续传输模式,数据长度为字。

?④?示例代码

数组偶数下标的数据为通道0采集数据,数组奇数下标的数据为通道1采集数据。

程序中将数组偶数下标数据加起来求平均值,实现均值滤波的功能,再将数据转换为电压值,即为PA0管脚的电压值。另一个通道同理。

uint32_t ADC_Value[100];  //数据缓存数组
uint8_t i;
uint32_t ad1, ad2;  //ad1存储PA0的电压值;ad2存储PA1的电压值

int main(void)
{
  HAL_Init();

  SystemClock_Config();

  MX_GPIO_Init();
  MX_USART1_UART_Init();
  MX_TIM1_Init();
  MX_DMA_Init();
  MX_ADC1_Init();

  HAL_TIM_Base_Start_IT(&htim1);
# 以DMA方式开启ADC转换。第二个参数是数据存储起始地址,第三个参数是DMA传输数据的长度。
  HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&ADC_Value, 100);  
  while (1)
  {
    HAL_Delay(500);
    for(i = 0,ad1 =0,ad2=0; i < 100;)
    {
        ad1 += ADC_Value[i++];
        ad2 += ADC_Value[i++];
    }
    ad1 /= 50;
    ad2 /= 50;
    printf("\r\n********ADC-DMA-Example********\r\n");
    printf("[\tmain]info:AD1_value=%1.3fV\r\n", ad1*3.3f/4096);
    printf("[\tmain]info:AD2_value=%1.3fV\r\n", ad2*3.3f/4096);
  }

13. IIC和SPI

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-02-28 15:45:41  更:2022-02-28 15:45:46 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 8:31:54-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码