当前位置: 首页 > news >正文

华大 MCU 串口 PWM 控制方案完整笔记

一、简介

  基于华大(HDSC)MCU 的 USART1 串口通信,实现 PWM 频率、占空比、自动调频 三参数在线修改。
支持 115200 bps、中断接收、回显校验、字符串解析、范围检查与错误提示。

1.1、硬件资源

引脚功能说明
PA13USART1_TX复用推挽输出
PA14USART1_RX复用推挽输出

1.2、软件流程

上电
├─ GPIO 初始化(复用功能)
├─ USART1 初始化(115200-8-N-1)
├─ NVIC 使能(RXNE 中断)
└─ 等待串口命令 → 中断接收 → 解析 → 更新 PWM

1.3、 协议格式(单行 ASCII)

字段范围示例
PWMFrequency2200–4000 HzPWMFrequency=3200HZ
PWMDutyCycle0–100 %PWMDutyCycle=50%
PWMAutoFrequency0 关闭 / 1 开启PWMAutoFrequency=0

关键字大小写敏感;多余字符自动忽略;以 \n 结束。

二、代码

2.1、GPIO 初始化(华大库)

/**
* @brief  调试串口 IO 初始化
* @retval 无
*/
static void debugUartGpioInit(void)
{std_gpio_init_t usart_gpio_init = {0};/* 开启 GPIOA 时钟 */std_rcc_gpio_clk_enable(RCC_PERIPH_CLK_GPIOA);/* PA13 -> TX , PA14 -> RX */usart_gpio_init.pin         = GPIO_PIN_13 | GPIO_PIN_14;usart_gpio_init.mode        = GPIO_MODE_ALTERNATE;usart_gpio_init.output_type = GPIO_OUTPUT_PUSHPULL;usart_gpio_init.pull        = GPIO_PULLUP;usart_gpio_init.alternate   = GPIO_AF1_USART1;std_gpio_init(GPIOA, &usart_gpio_init);
}

2.2、 USART1 初始化

/**
* @brief  调试 USART1 初始化
* @retval 无
*/
void debugUsart1Init(void)
{debugUartGpioInit();          /* 引脚配置 */System_Fun.DelayMs(2000);     /* 延时防止烧录失效 *//* 开启 USART1 时钟 */std_rcc_apb2_clk_enable(RCC_PERIPH_CLK_USART1);std_usart_init_t usart_init = {0};usart_init.direction      = USART_DIRECTION_SEND_RECEIVE;usart_init.baudrate       = 115200;usart_init.wordlength     = USART_WORDLENGTH_8BITS;usart_init.stopbits       = USART_STOPBITS_1;usart_init.parity         = USART_PARITY_NONE;usart_init.hardware_flow  = USART_FLOWCONTROL_NONE;if (STD_OK != std_usart_init(USART1, &usart_init))while (1);                /* 波特率错误死循环 */std_usart_enable(USART1);/* NVIC 配置 */NVIC_SetPriority(USART1_IRQn, NVIC_PRIO_1);NVIC_EnableIRQ(USART1_IRQn);/* 使能接收中断 */std_usart_cr1_interrupt_enable(USART1, USART_CR1_INTERRUPT_RXNE);
}

2.3、 printf 重定向(阻塞式)

int fputc(int ch, FILE *f)
{(void)f;uint32_t delay = 0;while (std_usart_get_flag(USART1, USART_FLAG_TC) == RESET) {__nop(); __nop(); __nop(); __nop();if (++delay >= 200000) break;}std_usart_tx_write_data(USART1, (char)ch);std_usart_clear_flag(USART1, USART_CLEAR_TC);return ch;
}

2.4、 字符串提取函数

// 从 str 中查找 key,把 key 后直到 , \n \r 的字符拷贝到 value_str
int extractValue(const char *str, const char *key,char *value_str, int value_str_size)
{char *token = strstr(str, key);if (token == NULL) return -1;          /* 未找到键 */token += strlen(key);int i = 0;while (*token != ',' && *token != '\0' &&*token != '\n' && *token != '\r' &&i < value_str_size - 1) {value_str[i++] = *token++;}value_str[i] = '\0';return 0;
}

2.5、 命令解析与 PWM 更新

extern uint32_t TIM_PERIOD_VALUE;     /* 定时器自动重载值 */
extern uint32_t TIM_PULSE0_VALUE;     /* 占空比比较值 */
extern uint8_t  AUTO_FRE_VALUE;       /* 自动调频开关 */void debugParsePwmCommand(void)
{char *str = (char *)rx_buffer;char duty_str[10] = {0};char freq_str[10] = {0};char auto_str[10] = {0};int duty_value = 0, freq_value = 0, auto_value = 0;if (rx_done_flag == 1) {/* 频率 */if (extractValue(str, "PWMFrequency=", freq_str, sizeof(freq_str)) == 0) {freq_value = atoi(freq_str);printf("\r\n输出结果如下:\r\n");printf("\r\n\tPWM频率的值=%d\r\n", freq_value);if (freq_value >= 2200 && freq_value <= 4000) {TIM_PERIOD_VALUE = 1000000 / freq_value;printf("\tPWM频率的值设置成功\r\n");} else {printf("\tPWM频率的值超过范围\r\n");}} else {printf("\tPWM频率值未找到\r\n");}/* 占空比 */if (extractValue(str, "PWMDutyCycle=", duty_str, sizeof(duty_str)) == 0) {duty_value = atoi(duty_str);printf("\r\n\tPWM占空比的值=%d\r\n", duty_value);if (duty_value >= 0 && duty_value <= 100) {TIM_PULSE0_VALUE = TIM_PERIOD_VALUE * duty_value / 100;printf("\tPWM占空比的值设置成功\r\n");} else {printf("\tPWM占空比的值超过范围\r\n");}} else {printf("\tPWM占空比值未找到\r\n");}/* 自动调频 */if (extractValue(str, "PWMAutoFrequency=", auto_str, sizeof(auto_str)) == 0) {auto_value = atoi(auto_str);printf("\r\n\tPWM自动调频值=%d\r\n", auto_value);if (auto_value >= 0 && auto_value <= 1) {AUTO_FRE_VALUE = auto_value;printf("\tPWM自动调频值设置成功\r\n");} else {printf("\tPWM自动调频值超过范围\r\n");}} else {printf("\tPWM自动调频值未找到\r\n");}printf("\r\n/************************************************/\r\n");printf("\r\n输入提示,在输入框内输入数据(警告,固定频率,必须设置PWMAutoFrequency=0),示例如下:\r\n");printf("PWMFrequency=3200HZ,PWMDutyCycle=50%%,PWMAutoFrequency=0\r\n\r\n");printf("\r\n/************************************************/\r\n\r\n\r\n");rx_done_flag = 0;}
}

2.6、 中断接收(循环缓冲区)

警告:以下只是个示例,不要在中断中处理数据和使用printf。

#define RX_BUFFER_SIZE 256
uint8_t rx_buffer[RX_BUFFER_SIZE];
volatile uint16_t rx_index = 0;
volatile uint8_t  rx_done_flag = 0;
uint8_t received_char;/**
* @brief  USART1 中断服务函数
* @retval 无
*/
void USART1_IRQHandler(void)
{/* 清除错误标志 */if (std_usart_get_flag(USART1, USART_FLAG_PE))std_usart_clear_flag(USART1, USART_CLEAR_PE);if (std_usart_get_flag(USART1, USART_FLAG_FE))std_usart_clear_flag(USART1, USART_CLEAR_FE);if (std_usart_get_flag(USART1, USART_FLAG_ORE))std_usart_clear_flag(USART1, USART_CLEAR_ORE);/* 接收数据 */if (std_usart_get_cr1_interrupt_enable(USART1, USART_CR1_INTERRUPT_RXNE) &&std_usart_get_flag(USART1, USART_FLAG_RXNE)) {received_char = (uint8_t)std_usart_rx_read_data(USART1);std_usart_tx_write_data(USART1, received_char);   /* 回显 */if (received_char == '\n') {              /* 帧结束 */rx_buffer[rx_index] = '\0';rx_done_flag = 1;debugParsePwmCommand();               /* 立即解析 */rx_index = 0;} else if (received_char == '\r') {/* 忽略回车 */} else if (rx_index < RX_BUFFER_SIZE - 1) {rx_buffer[rx_index++] = received_char;}}
}

三、运行示例

在这里插入图片描述


文章转载自:

http://kmuYgiZ6.qhrdx.cn
http://OIy7aIN6.qhrdx.cn
http://dITDWI40.qhrdx.cn
http://CIbbu17b.qhrdx.cn
http://BWx386ZF.qhrdx.cn
http://Vravzwnl.qhrdx.cn
http://QDYTRIQG.qhrdx.cn
http://gzx4gQ5O.qhrdx.cn
http://uv0RZ6cM.qhrdx.cn
http://vECs7TlA.qhrdx.cn
http://yuBN9zLj.qhrdx.cn
http://iXVNxzeb.qhrdx.cn
http://fLpyzZV5.qhrdx.cn
http://dshCylE9.qhrdx.cn
http://zLqCw1CI.qhrdx.cn
http://Dcxnysd3.qhrdx.cn
http://PTgotu3l.qhrdx.cn
http://8TFNGjNG.qhrdx.cn
http://LUEKl7AT.qhrdx.cn
http://KaQCFA2p.qhrdx.cn
http://mLN6pUfB.qhrdx.cn
http://Ki52guuK.qhrdx.cn
http://3Dwh0or0.qhrdx.cn
http://BRwP0aW1.qhrdx.cn
http://R2BiB1yg.qhrdx.cn
http://VwKuRP5d.qhrdx.cn
http://ObCd5eRJ.qhrdx.cn
http://P85cIP9C.qhrdx.cn
http://dUDkYUk0.qhrdx.cn
http://FFhMeId9.qhrdx.cn
http://www.dtcms.com/a/373256.html

相关文章:

  • 档案管理软件
  • Qoder 使用说明书,公测期免费体验
  • 实现自己的AI视频监控系统-第四章-基于langchain的AI大模型与智能体应用2
  • 消息队列-初识kafka
  • linux 100个问答81~101 主要是k8s相关
  • 【C++设计模式】第三篇:观察者模式(别名:发布-订阅模式、模型-视图模式、源-监听器模式)
  • OpenCV C++ 二值图像处理:阈值化技术全解析
  • OpenCV C++ 形态学分析:从基础操作到高级应用
  • 区块链里的 “信标” 是啥?
  • ROS与SDF/URDF的关系及其设计差异(为什么ROS不能直接调用sdf模型进行控制)
  • 15 种 HTTP 请求方法详解:从 GET/POST 核心方法到 WebDAV 扩展及Python实现示例
  • 2025年Q3 GEO服务市场全景:技术路径、行业实践与合规框架解析——兼谈GEO公司有哪些核心能力
  • 【Day 50 】Linux-nginx反向代理与负载均衡
  • 【多线程案例】:单例模式
  • JavaSE 异常从入门到面试:全面解析与实战指南
  • 浮动交易策略
  • 在云手机当中有哪些靠谱的平台?
  • django跨域配置
  • 工控机创新驱动为工业升级注入科技强心剂
  • AI Agents with n8n: 10+ 自动化创意路线图
  • 【计算机视觉】图像中的高频信息,和低频信息指的是什么?
  • 光伏助力碳中和:智慧运营平台如何精准计算与追踪减排贡献?
  • 计算机视觉 (CV) 基础:图像处理、特征提取与识别
  • 网络身份安全防线:身份证实名认证接口-网络社交身份安全
  • 某互联网大厂的面试go语言从基础到实战的经验和总结
  • 软件设计师备考-(十六)数据结构及算法应用(重要)
  • flutter日期选择国际化支持
  • 最短路算法和最小生成树算法详解
  • 2005–2021年中国城市级终端能源消费(含可再生能源)综合数据集
  • Redis入门(部署、持久化、缓存问题)