1 STM32C0基本功能的实现
GPIO、UART、PWM是MCU开发的基本功能,也是实现多种功能的基础。因为开发流程相似,集中在一个帖子中。
首先需要下载安装STM32CubeIDE,然后下载对应STM32C071的软件包,基本驱动和范例都在里面。

2 GPIO评测
2.1 STM32C071 是一款由 STMicroelectronics 制造的微控制器,属于 STM32 C0 系列的一部分。这款微控制器具有低功耗和高性能的特点,适用于各种嵌入式应用。在 STM32C071 中,GPIO(通用输入/输出)控制是基本功能之一,允许用户通过编程来控制外部设备。
GPIO 基础
GPIO 引脚可以配置为输入或输出,并可以进一步配置为推挽、开漏、模拟、复用推挽或复用开漏模式。这些配置允许 GPIO 引脚适应不同的应用场景。
配置 GPIO
在 STM32 微控制器中,GPIO 的配置通常涉及以下几个步骤:
初始化 GPIO 引脚:设置 GPIO 引脚的模式(输入、输出、复用功能、模拟)。
设置 GPIO 输出类型:选择推挽或开漏输出。
配置 GPIO 速度:设置 GPIO 引脚的输出速度。
配置 GPIO 上拉/下拉:设置 GPIO 引脚的上拉或下拉电阻。
示例代码
以下是一个使用 HAL 库配置 STM32C071 GPIO 引脚的示例代码:
#include "main.h"
int main(void)
{
HAL_Init();
SystemClock_Config();
BSP_LED_Init(LED1);
EXTI4_15_IRQHandler_Config();
while (1)
{
}
}
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
__HAL_FLASH_SET_LATENCY(FLASH_LATENCY_1);
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSIDiv = RCC_HSI_DIV1;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
{
Error_Handler();
}
}
static void EXTI4_15_IRQHandler_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
__HAL_RCC_GPIOC_CLK_ENABLE();
GPIO_InitStructure.Mode = GPIO_MODE_IT_FALLING;
GPIO_InitStructure.Pull = GPIO_PULLUP;
GPIO_InitStructure.Pin = BUTTON_USER_PIN;
HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
HAL_NVIC_SetPriority(EXTI4_15_IRQn, 2, 0);
HAL_NVIC_EnableIRQ(EXTI4_15_IRQn);
}
void HAL_GPIO_EXTI_Falling_Callback(uint16_t GPIO_Pin)
{
if (GPIO_Pin == BUTTON_USER_PIN)
{
BSP_LED_Toggle(LED1);
}
}
确保在配置 GPIO 之前使能相应的 GPIO 时钟。
根据应用需求选择合适的 GPIO 模式和速度。
在处理 GPIO 输入时,注意上拉和下拉电阻的配置,以避免不确定的状态。
通过正确配置和控制 GPIO,STM32C071 可以与各种外部设备进行交互,实现丰富的功能。
2.2 编译成功
2.3 下载并演示
首先需要升级stlink
升级过程中

这个逻辑是检测用户按键的状态,每次点击切换led的状态,则启动中断,切换为亮暗亮暗的循环。

动图视频

3 UART 评测
3.1 STM32C071 MCU 支持多个 UART (通用异步收发器) 外设,通常称为 USART (通用同步/异步收发器),因为它也具备同步通信能力。UART 主要用于串行通信,常用于与传感器、调试器、PC 等设备进行数据交换。
以下是使用 STM32C071 控制 UART 的一些关键步骤和说明
- 硬件准备:
连接: 将 STM32C071 的 UART TX (发送) 引脚连接到接收设备的 RX (接收) 引脚,将 STM32C071 的 UART RX (接收) 引脚连接到发送设备的 TX (接收) 引脚。通常还需要连接 GND (地线)。
引脚选择: STM32C071 有多个 UART 外设 (例如 USART1, USART2, USART3, UART4, UART5 等),每个外设都有其默认或复用的 TX 和 RX 引脚。
USART1: PA9 (TX), PA10 (RX)
USART2: PA2 (TX), PA3 (RX)
电平匹配: 确保通信双方的电平匹配 (例如,都是 3.3V TTL 或 5V TTL)。如果需要与 RS232 设备通信,需要电平转换器 (如 MAX232)。
使能外设时钟: 确保在 RCC 配置中为所选 UART 外设启用了时钟。
配置引脚: 将对应的 TX 和 RX 引脚设置为 "USART TX" 和 "USART RX" 模式。CubeMX 会自动处理复用功能。
配置参数:
Baud Rate (波特率): 设置通信速率,如 9600, 115200 等。确保与接收端设置一致。
Word Length (字长): 选择 7 bits。
Stop Bits (停止位): 选择1。
Parity (校验位): 选择 None (无校验)。
Hardware Flow Control (硬件流控): 通常选择 None (无流控)。
Mode: 选择 "TX" (仅发送), "RX" (仅接收) 或 "TX/RX" (收发)
3.2 代码和说明

使用的代码主要部分如下
int main(void)
{
HAL_Init();
SystemClock_Config();
BSP_LED_Init(LED1);
MX_GPIO_Init();
MX_USART2_UART_Init();
printf("\n\r UART Printf Example: retarget the C library printf function to the UART\n\r");
printf("** Test finished successfully. ** \n\r");
while (1)
{
}
}
3.3 下载并演示

输出结果需要修改串口函数为115200-7-1

否则就是乱码

4 PWM输出评测
4.1 STM32C071 微控制器具有多个定时器 (TIM),其中许多定时器支持 PWM (脉冲宽度调制) 功能。PWM 常用于控制电机速度、LED 亮度、功率转换器等。
WM 原理: PWM 通过快速开关信号输出,控制信号的“接通”时间(脉冲宽度)与“断开”时间的比例(占空比),从而在平均效果上模拟不同的电压或功率水平。
定时器角色: STM32 的通用定时器 (General Purpose Timers, TIMx) 和高级定时器 (Advanced Timers, TIM1, TIM8) 通常用于生成 PWM 信号。
自动重装载寄存器 (ARR): 定义 PWM 信号的周期 (频率)。
捕获/比较寄存器 (CCR): 定义 PWM 信号的占空比。
预分频器 (PSC): 配置定时器时钟源的分频,影响频率。
通道 (Channel): 定时器通常有多个通道 (如 Channel 1, 2, 3, 4),每个通道可以输出独立的 PWM 信号。
输出比较功能: PWM 通常利用定时器的输出比较功能实现。
选择定时器和通道: 根据需求选择一个可用的定时器 TIM3 和其通道 Channel 2
选择 GPIO 引脚: 查找所选定时器通道对应的复用功能 GPIO 引脚。
TIM3_CH1: PA6

连接到led灯。
4.2 代码和说明

核心代码如下,主要是用户按键控制下调整PWM的过程。调整占空比,而PWM的时钟频率由计时器TIMER来启动
__STATIC_INLINE void Configure_DutyCycle(uint32_t D)
{
uint32_t P; /* Pulse duration */
uint32_t T; /* PWM signal period */
/* PWM signal period is determined by the value of the auto-reload register */
T = LL_TIM_GetAutoReload(TIM3) + 1;
/* Pulse duration is determined by the value of the compare register. */
/* Its value is calculated in order to match the requested duty cycle. */
P = (D*T)/100;
LL_TIM_OC_SetCompareCH1(TIM3, P);
}
/******************************************************************************/
/* USER IRQ HANDLER TREATMENT */
/******************************************************************************/
/**
* @brief User button interrupt processing
* @note When the user key button is pressed the PWM duty cycle is updated.
* @param None
* @retval None
*/
void UserButton_Callback(void)
{
/* Set new duty cycle */
iDutyCycle = (iDutyCycle + 1) % TIM_DUTY_CYCLES_NB;
/* Change PWM signal duty cycle */
Configure_DutyCycle(aDutyCycle[iDutyCycle]);
}
/**
* @brief Timer capture/compare interrupt processing
* @param None
* @retval None
*/
void TimerCaptureCompare_Callback(void)
{
uint32_t CNT, ARR;
CNT = LL_TIM_GetCounter(TIM3);
ARR = LL_TIM_GetAutoReload(TIM3);
if (LL_TIM_OC_GetCompareCH1(TIM3) > ARR )
{
/* If capture/compare setting is greater than autoreload, there is a counter overflow and counter restarts from 0.
Need to add full period to counter value (ARR+1) */
CNT = CNT + ARR + 1;
}
uwMeasuredDutyCycle = (CNT * 100) / ( ARR + 1 );
}
4.3 下载和演示

演示如下

5 小结
综合上述过程,可以看到,采用STM32CubeIDE进行开发,逻辑清晰,配置丰富。可以快速开始上手。