STM32F103系列:四路串口通讯项目程序及ADC、PWM与FLASH存储方案
STM32F103系列多串口通讯项目程序 四路串口转通讯,ADC采集,PWM多路通道,FLSAH存储 可以提供原理图PDF。 PCB另外
最近在搞STM32F103多串口项目的时候,发现这老伙计虽然年纪大了但干活还挺利索。四路串口全开还能顺带做ADC采集和PWM输出,实测主频跑到72MHz没掉链子。先上点硬货,看看怎么让四个串口同时干活:
void MX_USART_Init(void) {
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
HAL_UART_Init(&huart1);
// 同理初始化UART2、UART3、UART4
// 特别注意UART4的时钟要开APB1
}
这里有个坑要注意:UART4挂在APB1总线,初始化前记得HALRCCUART4CLKENABLE(),别问我怎么知道的。接收建议用DMA+IDLE中断,实测115200波特率下四个串口同时收发数据也没见丢包。

ADC采集这块,用规则组循环扫描挺省事:
void ADC_Config() {
hadc.Instance = ADC1;
hadc.Init.ScanConvMode = ENABLE;
hadc.Init.ContinuousConvMode = ENABLE;
hadc.Init.NbrOfConversion = 4; // 四通道
HAL_ADC_Init(&hadc);
ADC_ChannelConfTypeDef sConfig = {0};
sConfig.Rank = 1;
sConfig.Channel = ADC_CHANNEL_0; // PA0
HAL_ADC_ConfigChannel(&hadc, &sConfig);
// 重复配置其他三个通道
}
采集时直接HALADCStartDMA(&hadc, adcbuffer, 4),记得提前校准。实测发现电源纹波大的话可以加个软件滤波,比如滑动平均法,手速够快的话直接寄存器操作采样时间拉长。
STM32F103系列多串口通讯项目程序 四路串口转通讯,ADC采集,PWM多路通道,FLSAH存储 可以提供原理图PDF。 PCB另外

PWM输出用TIM1和TIM2的组合拳:
void PWM_Init() {
htim1.Instance = TIM1;
htim1.Init.Prescaler = 71; // 1MHz计数
htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
htim1.Init.Period = 999; // 1kHz频率
HAL_TIM_PWM_Init(&htim1);
TIM_OC_InitTypeDef sConfigOC = {0};
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 500; // 50%占空比
HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1);
// 其他通道同理
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
}
改占空比直接HALTIMSETCOMPARE(&htim1, TIMCHANNEL1, value),实测频率上到50kHz波形还是方方正正的。注意TIM1是高级定时器,输出前记得TIMCCxCmd()使能通道。
Flash存储最头疼的是擦写次数,建议做个磨损均衡。存数据前先查空白页:
uint32_t Find_Empty_Page() {
uint32_t page_addr = FLASH_BASE + 0x8000; // 从第32页开始
while(page_addr < FLASH_END) {
if(*(__IO uint32_t*)page_addr == 0xFFFFFFFF)
return page_addr;
page_addr += 0x400; // 每页1KB
}
return 0; // 没空页了
}
写数据时注意半字对齐,HALFLASHUnlock()之后用HALFLASHProgram(FLASHTYPEPROGRAMHALFWORD, address, data),写完记得Lock()。重要数据建议加CRC校验,掉电前赶紧保存。

调试时发现四路串口同时跑容易卡DMA,后来把UART1的优先级调低解决了。ADC和PWM倒是相处融洽,只要别在PWM中断里搞复杂运算。整个项目下来感觉F103的存储空间确实紧张,后来把不用的库函数全删了才腾出地方。需要原理图的朋友可以私信,PCB布板时记得模拟数字地分开,特别是ADC参考电压那路要单独处理。
更多推荐
所有评论(0)