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 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> hal库:STM32CubeMX配置与使用(含Free RTOS) -> 正文阅读

[嵌入式]hal库:STM32CubeMX配置与使用(含Free RTOS)

硬件:正点原子STM32F103ZET6

(一 )基础配置

1.必须配置:

①配置板子型号/封装:

②配置时钟:外部晶振

③配置时基:串行总线调试(否则只能下载一次)、系统滴答定时器

④配置时钟树:HCLK输入72MHZ主频,回车自动分配时钟树

⑤配置工程名/IDE:

⑥配置分离.c/.h文件:

好了,你可以右上角Generate Code生成一个没有任何功能的代码。

2.需求配置:

①配置定时器/定时器中断:

定时计算公式:

Tout = ((arr+1)*(psc+1))/Tclk ;
Tclk:定时器的输入时钟频率(单位MHZ)
?Tout:定时器溢出时间(单位为us)
? .TIM_Period = arr; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?eg;4999(周期)
? .TIM_Prescaler = psc; ? ? ? ? ? ? ? ? ? ? ? ? ? ? eg:7199(预分频)
? Tout = ((4999+1)×(7199+1))/72 = 500000us = 500ms ??

? Tout = ((9999+1)×(7199+1))/72 = 500000us = 1s ??

②配置LED:使能GPIO输出

初始电平:高电平(由程序改动,低电平有效)

模式:推挽输出

引脚上拉:初始3.3V电平

设置标签:提高代码复用性

?

③配置蜂鸣器:使能GPIO输出

初始电平:低电平(由程序改动,高电平有效)

模式:推挽输出

引脚上拉:初始3.3V电平

设置标签:提高代码复用性

④配置按键中断:使能GPIO中断(如不使用中断控制则配置按键为GPIO_Input)

NVIC使能

GPIO模式:下降沿触发

引脚上拉:初始接3.3V高电平

??

⑤配置串口/串口中断:异步收发(选后右边自动使能引脚)

3.FreeRTOS配置:

①V1版本,V2有点问题

②不用Systick作为时基,选择另一定时器作为时基

④使能定时器:

创建定时器函数

(二)基础代码(以下程序都写在main.c)

注意:代码写在begin和end间,不然加引脚后重新用cubemx生成新代码,你写的代码会消失!

按键GPIO_Input法1:延时消抖

  /* USER CODE BEGIN 3 */
     if(HAL_GPIO_ReadPin(KEY0_GPIO_Port,KEY0_Pin)==GPIO_PIN_RESET)
     {
                HAL_Delay(10);
         if(HAL_GPIO_ReadPin(KEY0_GPIO_Port,KEY0_Pin)==GPIO_PIN_RESET){
             HAL_GPIO_WritePin(LED0_GPIO_Port,LED0_Pin,GPIO_PIN_RESET);
         } 
     while(HAL_GPIO_ReadPin(KEY0_GPIO_Port,KEY0_Pin)==GPIO_PIN_RESET);
     }
  /* USER CODE END 3 */

按键GPIO_Input法2:工业一般采用状态机消抖(延时方法CPU效率降低)

/* USER CODE BEGIN PTD */
typedef enum{
    KEY_CHECK = 0,
    KEY_COMFIRM,
    KEY_RELEASE
}KEY_STATE;
/* USER CODE END PTD */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
KEY_STATE KeyState = KEY_CHECK;
uint8_t  KeyFlag = 0;
/* USER CODE END PV */
 /* USER CODE BEGIN 2 */
    int carIN =0;
    HAL_TIM_Base_Start_IT(&htim6);
  /* USER CODE END 2 */
 /* USER CODE BEGIN 3 */
     if(KeyFlag ==1){
        KeyFlag = 0;
        HAL_GPIO_TogglePin(LED0_GPIO_Port,LED0_Pin); 
     }
  }
  /* USER CODE END 3 */
/* USER CODE BEGIN 4 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef * htim){
    if(htim ->Instance == TIM6){
        switch(KeyState){
            case KEY_CHECK:{
                if(HAL_GPIO_ReadPin(KEY0_GPIO_Port,KEY0_Pin)== GPIO_PIN_RESET){
                    KeyState = KEY_COMFIRM;
                }
                break;
            }
            case KEY_COMFIRM:{
            if(HAL_GPIO_ReadPin(KEY0_GPIO_Port,KEY0_Pin)== GPIO_PIN_RESET){
                KeyState = KEY_RELEASE;
                    KeyFlag =1;
                }else{
                    KeyState = KEY_CHECK;
                }
                    break;
            }
            case KEY_RELEASE:{
                if(HAL_GPIO_ReadPin(KEY0_GPIO_Port,KEY0_Pin)== GPIO_PIN_SET){
                    KeyState = KEY_CHECK;
                }
                break;
            }
            default: break;
        }
    }
}
/* USER CODE END 4 */

按键GPIO_Exit法1:中断回调函数里,按下KEY0后LED0亮灭

/* USER CODE BEGIN 4 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){
    if(GPIO_Pin == KEY0_Pin){
        HAL_GPIO_TogglePin(LED0_GPIO_Port,LED0_Pin); 
    }
}
/* USER CODE END 4 */

按键中断GPIO_Exit法2:多个按键中断选择

/* USER CODE BEGIN 4 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){
    switch(GPIO_Pin){
        case KEY0_Pin:{
            HAL_GPIO_TogglePin(LED0_GPIO_Port,LED0_Pin); 
            break;
        }   
        case KEY1_Pin:{
            HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin); 
            break;
        }
        default: break;
    }
}
/* USER CODE END 4 */

串口法1:不使用重定向

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
uint8_t Temp[10];
/* USER CODE END PM */
 ?  /* USER CODE BEGIN 3 */
    if(HAL_UART_Receive(&huart1,Temp,5,100)== HAL_OK){
            HAL_UART_Transmit(&huart1,Temp,5,100);
    }
  }
  /* USER CODE END 3 */

串口使用重定向注意:

1.printf的时候加fput重定向函数了吗?

int fputc(int ch, FILE *f)
{
  HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff);
  return ch;
}
int fgetc(FILE *f)
{
  uint8_t ch = 0;
  HAL_UART_Receive(&huart1, &ch, 1, 0xffff);
  return ch;
}

2.Keil的Micro 微库勾了吗?

3.#include "stdio.h"加了吗?

串口法2:使用重定向

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h"
/* USER CODE END Includes */
  /* USER CODE BEGIN 2 */
    printf("INPUT:\r\n");
     char RecData;
  /* USER CODE END 2 */
 /* USER CODE BEGIN 3 */
    scanf("%c",&RecData);
    if(RecData == 'y')
    {
        printf("Receive y\r\n");
    }else{
        printf("Receive others\r\n");
    }
  }
  /* USER CODE END 3 */
/* USER CODE BEGIN 4 */
int fputc(int ch,FILE*f){
    HAL_UART_Transmit(&huart1,(uint8_t*)&ch,1,HAL_MAX_DELAY);
    return ch;
}
int fgetc(FILE*f){
    uint8_t ch;
    HAL_UART_Receive(&huart1,(uint8_t*)&ch,1,HAL_MAX_DELAY);
    return ch;
}
/* USER CODE END 4 */

串口法3:使用scanf

  /* USER CODE BEGIN 2 */
    printf("INPUT:\r\n");
  /* USER CODE END 2 */
/* USER CODE BEGIN 3 */
 ? ?  char str[10]; 
 ? ? printf("请输入字符串:");
 ? ?  scanf("%s",str); 
 ? ? printf("输出结果:%s\r\n",str);
     
  }
  /* USER CODE END 3 */

串口法4:使用条件编译,方便串口调试时设置1打log,出产品时设置0

/* USER CODE BEGIN PD */
#define Log 1
/* USER CODE END PD */
  /* USER CODE BEGIN 3 */
  #if Log
        printf("stm32");
    #endif
    }
  /* USER CODE END 3 */

串口法5:使用格式化条件编译,区分info、debug、error时log

/* USER CODE BEGIN Includes */
#include "stdio.h"
#define USER_MAIN_DEBUG //define or annotation
?
#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
/* USER CODE END Includes */
 ?  /* USER CODE BEGIN 3 */
 user_main_info("hello stm32");
    }
  /* USER CODE END 3 */

(三)FreeRTOS代码(以下程序都写在freertos.c)

定时器例1:(usart.c加fputc勾微库)

#include "stdio.h"
  /* USER CODE BEGIN RTOS_TIMERS */
  /* start timers, add new ones, ... */
osTimerStart(myTimer01Handle,1000);//1秒钟启动一次定时
  /* USER CODE END RTOS_TIMERS */
/* Callback01 function */
void Callback01(void const * argument)
{
  /* USER CODE BEGIN Callback01 */
 static int32_t count = 0;
  printf( "定时器计数:%d.\r\n",count++);
  /* USER CODE END Callback01 */
}

定时器例2:(usart.c加fputc勾微库)

  /* USER CODE BEGIN RTOS_TIMERS */
  /* start timers, add new ones, ... */
    osTimerStart(myTimer01Handle,1000);//1秒钟启动一次定时
  /* USER CODE END RTOS_TIMERS */
/* Callback01 function */
void Callback01(void const * argument)
{
  /* USER CODE BEGIN Callback01 */
        HAL_GPIO_TogglePin(LED0_GPIO_Port,LED0_Pin); 
  /* USER CODE END Callback01 */
}

消息队列:打印hello(加fputc)

1.创建两个任务:用于数据接送和发送

2.一般不用cubemx生成消息队列:有点问题,自己写程序

/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes */
QueueHandle_t DataQueue;
/* USER CODE END FunctionPrototypes */
  /* USER CODE BEGIN RTOS_QUEUES */
  /* add queues, ... */
    DataQueue = xQueueCreate(2,9);
  /* USER CODE END RTOS_QUEUES */
void DataSendTask(void const * argument)
{
  /* USER CODE BEGIN DataSendTask */
    uint8_t buf[9] = "hello\r\n";
  /* Infinite loop */
  for(;;)
  {
        HAL_GPIO_TogglePin(LED0_GPIO_Port,LED0_Pin); 
        xQueueSend(DataQueue,buf,10);
 ?  osDelay(1);
  }
  /* USER CODE END DataSendTask */
void DataReceiveTask(void const * argument)
{
  /* USER CODE BEGIN DataReceiveTask */
    uint8_t buf[9];
  /* Infinite loop */
  for(;;)
  {
        if(pdPASS == xQueueReceive(DataQueue,buf,10)){
            printf(buf);
        }
 ?  osDelay(1);
  }

中断

/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){
?
}
/* USER CODE END Application */

任务通知:按键0翻转LED0

/* USER CODE END Header_StartLED2Task */
void StartLED2Task(void const * argument)
{
  /* USER CODE BEGIN StartLED2Task */
    static uint8_t count =0;
    uint32_t NotifyValue;
    BaseType_t err;
  /* Infinite loop */
  for(;;)
  {
        err = xTaskNotifyWait(0x00,0xFFFFFFF,&NotifyValue,portMAX_DELAY);
        if(err == pdPASS){
            if((NotifyValue&0x01)!=0){
                if(count == 1){
                    HAL_GPIO_WritePin(LED0_GPIO_Port,LED0_Pin,GPIO_PIN_RESET);
                    count =0;
                }
                else{
                    HAL_GPIO_WritePin(LED0_GPIO_Port,LED0_Pin,GPIO_PIN_SET); 
                    count =1;
                }
            }
        }
  }
  /* USER CODE END StartLED2Task */
}
/* USER CODE BEGIN Application */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){
    BaseType_t YieldRequired;
    if(GPIO_Pin == KEY0_Pin){
         xTaskNotifyFromISR(LED2TaskHandle,0x01,eSetBits,&YieldRequired);
        portYIELD_FROM_ISR(YieldRequired);
    }
}
/* USER CODE END Application */

任务挂起恢复:亮两次挂起按键0恢复LED

/* USER CODE END Header_StartLED2Task */
void StartLED2Task(void const * argument)
{
  /* USER CODE BEGIN StartLED2Task */
    static uint8_t count =0;
  /* Infinite loop */
  for(;;)
  {
        HAL_GPIO_TogglePin(LED0_GPIO_Port,LED0_Pin); 
 ?  osDelay(300);
        
        count++;
        if(count>3){
            count =0;
            vTaskSuspend(NULL);
        }
  }
  /* USER CODE END StartLED2Task */
}
/* USER CODE BEGIN Application */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){
    BaseType_t YieldRequired;
    if(GPIO_Pin == KEY0_Pin){
            YieldRequired = xTaskResumeFromISR(LED2TaskHandle);
            if(YieldRequired == pdTRUE){
                    portYIELD_FROM_ISR(YieldRequired);
            }
    }
}
/* USER CODE END Application */
  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-02-28 15:45:41  更:2022-02-28 15:47:39 
 
开发: 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:26:11-

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