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参考电压那路要单独处理。

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐