ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

STM32外设驱动封装实战:GPIO、输入捕获与编码器接口

STM32外设驱动封装实战:GPIO、输入捕获与编码器接口 1. 引言在STM32嵌入式开发中直接操作寄存器或反复调用标准库函数虽然灵活但代码复用性差、可读性不高对新手尤其不友好——稍不留神漏掉一条时钟使能或初始化指令功能就无法实现排查起来也很费劲。本文分享一套面向新手的 STM32 外设简易封装库把 GPIO、输入捕获测频/测占空比、编码器接口、ADC 采集、DMA 传输等常用外设的初始化与读取封装成一个个函数。你只需要照着注释填参数、按顺序调用即可不用关心底层寄存器细节也不用担心漏写配置指令。后续还会持续补充 SPI、I2C、看门狗等更多外设的简易配置逐步形成一套属于自己的「STM32 快速开发工具箱」。配套资源下载本文配套的完整工程代码已打包上传可通过夸克网盘获取链接https://pan.quark.cn/s/95809e5ce13b?pwdGjmb提取码Gjmb打开「夸克网盘APP」即可下载stm32_1.zip内含本文所有封装函数的可直接运行的工程模板。2. GPIO 驱动封装GPIO通用输入输出是最基础的外设。这里以初始化函数为例其余函数功能简述如下。2.1 GPIO 初始化函数/** * 函 数GPIO初始化配置 * 参 数a - GPIO端口指针如GPIOA * 参 数b - GPIO引脚号如GPIO_Pin_0 * 参 数GPIO_Mode - GPIO工作模式如GPIO_Mode_AF_PP * 返 回 值无 */voidgpiostart(GPIO_TypeDef*a,uint16_tb,GPIOMode_TypeDef GPIO_Mode){GPIO_InitTypeDef gpio_a;gpio_a.GPIO_ModeGPIO_Mode;gpio_a.GPIO_Pinb;gpio_a.GPIO_SpeedGPIO_Speed_50MHz;GPIO_Init(a,gpio_a);GPIO_ResetBits(a,b);}说明该函数将端口、引脚、模式作为参数传入内部统一配置50MHz速度并在初始化后默认输出低电平。调用示例gpiostart(GPIOA,GPIO_Pin_0,GPIO_Mode_Out_PP);// PA0推挽输出2.2 其他 GPIO 封装函数gpioblink(a, b, c, GPIO_Mode)完成一次“高-低-高”的闪烁动作适合LED指示或简单脉冲输出。gpiochange(GPIO_Remap1, GPIO_Remap2, GPIO_Remap3)引脚重映射配置。注意会占用AFIO并可能关闭JTAG/SWD调试口非必要不要使用。keytim(a, b, c)按键定时扫描返回按键状态。keyzhuan(a, b, c, d)按键状态转换/消抖处理。调用示例示例代码后续将随资源包更新补充// LED闪烁PA0推挽输出每200ms翻转一次gpioblink(GPIOA,GPIO_Pin_0,200,GPIO_Mode_Out_PP);// 按键扫描PA1上拉输入每10ms扫描一次intkey_statekeytim(GPIOA,GPIO_Pin_1,10);if(key_state1){// 按键按下执行对应操作}3. 串口USART驱动封装串口是嵌入式开发中最常用的调试与通信手段。这里以 USART1PA9TXPA10RX为例封装了初始化、发送、以及两种实用的帧解析功能。3.1 串口初始化/** * 函 数USART1 PA9(TX)/PA10(RX) GPIO初始化 * 参 数无 * 返 回 值无 * 说 明PA9复用推挽输出PA10上拉输入 */voidserial_init_u1_pa910(void){RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_ModeGPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_PinGPIO_Pin_9;GPIO_InitStructure.GPIO_SpeedGPIO_Speed_50MHz;GPIO_Init(GPIOA,GPIO_InitStructure);GPIO_InitStructure.GPIO_ModeGPIO_Mode_IPU;GPIO_InitStructure.GPIO_PinGPIO_Pin_10;GPIO_InitStructure.GPIO_SpeedGPIO_Speed_50MHz;GPIO_Init(GPIOA,GPIO_InitStructure);}/** * 函 数USART参数初始化配置 * 参 数USART_BaudRate - 波特率 * 参 数USART_HardwareFlowControl - 硬件流控制 * 参 数USART_Mode - 工作模式发送/接收 * 参 数USART_Parity - 校验位 * 参 数USART_StopBits - 停止位 * 参 数USART_WordLength - 数据位长度 * 返 回 值无 */voidusart_init_txd(uint16_tUSART_BaudRate,uint16_tUSART_HardwareFlowControl,uint16_tUSART_Mode,uint16_tUSART_Parity,uint16_tUSART_StopBits,uint16_tUSART_WordLength){USART_InitTypeDef a;a.USART_BaudRateUSART_BaudRate;a.USART_HardwareFlowControlUSART_HardwareFlowControl;a.USART_ModeUSART_Mode;a.USART_ParityUSART_Parity;a.USART_StopBitsUSART_StopBits;a.USART_WordLengthUSART_WordLength;USART_Init(USART1,a);USART_Cmd(USART1,ENABLE);}说明serial_init_u1_pa910()完成引脚复用配置usart_init_txd()完成串口参数配置。调用示例serial_init_u1_pa910();usart_init_txd(115200,USART_HardwareFlowControl_None,USART_Mode_Rx|USART_Mode_Tx,USART_Parity_No,USART_StopBits_1,USART_WordLength_8b);3.2 串口发送函数/** * 函 数串口发送单个字节底层函数 * 参 数USARTx - USART指针 * 参 数Data - 待发送数据 * 返 回 值无 */voidchuankou(USART_TypeDef*USARTx,uint16_tData){USART_SendData(USARTx,Data);while(USART_GetFlagStatus(USARTx,USART_FLAG_TXE)RESET);}/** * 函 数串口发送字节数组 * 参 数USARTx - USART指针 * 参 数Array - 数组首地址 * 参 数Length - 数组长度 * 返 回 值无 */voidchuankou_SendArray(USART_TypeDef*USARTx,uint8_t*Array,uint16_tLength){uint16_ti;for(i0;iLength;i){chuankou(USARTx,Array[i]);}}/** * 函 数串口发送字符串 * 参 数USARTx - USART指针 * 参 数String - 字符串指针 * 返 回 值无 */voidchuankou_SendString(USART_TypeDef*USARTx,char*String){uint8_ti;for(i0;String[i]!\0;i){chuankou(USARTx,String[i]);}}说明三个发送函数由底层到高层依次封装分别支持发送单字节、字节数组和字符串满足不同场景需求。3.3 字符帧解析帧格式 字符串 \rstaticuint8_tchar_restat0;staticuint8_tchar_index0;chartack_char[100];/** * 函 数字符帧启动并解析 * 参 数first_byte - 已读取的帧头字节 * 返 回 值无 * 说 明帧格式 字符串 \r */staticvoidchar_frame_start(uint8_tfirst_byte){char_restat1;char_index0;}staticvoiduart_parse_char(uint8_tbyte){if(char_restat1){if(byte\r){tack_char[char_index]\0;// 字符串结束符char_restat0;S1;// 通知主循环}else{if(char_index99){tack_char[char_index]byte;char_index;}// 超长截断防止溢出}}}说明以作为帧头遇到\r表示一帧结束解析结果存入tack_char并置位标志S主循环检测到后即可处理。3.4 数值帧解析帧格式0xFF 4字节数据 0xFEstaticuint8_tnum_restat0;staticuint8_tnum_buf[4];staticuint8_tnum_index0;uint8_ttack_data[4];/** * 函 数数值帧启动并解析 * 参 数first_byte - 已读取的帧头字节0xFF * 返 回 值无 * 说 明帧格式 0xFF 4字节数据 0xFE */staticvoidnum_frame_start(uint8_tfirst_byte){num_restat1;num_index0;}staticvoiduart_parse_num(uint8_tbyte){if(num_restat1){num_buf[num_index]byte;num_index;if(num_index4){num_restat2;num_index0;}}elseif(num_restat2){if(byte0xFE){// 接收完成拷贝到全局数据区for(inti0;i4;i){tack_data[i]num_buf[i];}num_restat0;S1;// 通知主循环}else{// 帧尾不对重置num_restat0;}}}说明以0xFF作为帧头接收 4 字节数据后等待0xFE帧尾校验通过后存入tack_data并置位标志S。这种定长帧格式非常适合传输传感器数据或控制指令。3.5 其他串口封装函数Serial_GetRxFlag()获取串口接收标志位并自动清零返回 1 表示收到新数据。Serial_SendByte(Byte)发送单个字节并等待发送完成。ustar_rxd()接收数据回传测试将收到的数据原样发回。us_send_U1()/us_send2_U1()串口发送封装配合中断处理函数使用。USART1_IRQHandler_char()/USART1_IRQHandler_num()中断接收处理分别调用字符帧或数值帧解析。注意帧解析函数需要在USART1_IRQHandler中断服务函数中调用将接收到的每个字节喂给对应的解析函数。4. 定时器与 PWM 驱动封装定时器是 STM32 中最常用的外设之一既能做定时中断也能输出 PWM 波形驱动电机、舵机等。这里封装了定时器初始化、PWM 输出与动态调节等函数。4.1 定时器内部时钟初始化/** * 函 数TIM定时器内部时钟初始化APB1 * 参 数RCC_APB1Periph_ - APB1外设时钟使能宏如RCC_APB1Periph_TIM2 * 参 数TIMX - 定时器指针如TIM2 * 参 数TIM_ClockDivision - 时钟分频因子如TIM_CKD_DIV1 * 参 数TIM_CounterMode - 计数模式如TIM_CounterMode_Up * 参 数ARR - 自动重装载值 * 参 数PSC - 预分频器值 * 参 数TIM_RepetitionCounter - 重复计数器值高级定时器用通用填0 * 返 回 值无 * 说 明溢出频率 主频 / (PSC1) / (ARR1) */voidtimer_init_APB1_in(uint32_tRCC_APB1Periph_,TIM_TypeDef*TIMX,uint16_tTIM_ClockDivision,uint16_tTIM_CounterMode,intARR,intPSC,intTIM_RepetitionCounter){RCC_APB1PeriphClockCmd(RCC_APB1Periph_,ENABLE);TIM_InternalClockConfig(TIMX);TIM_TimeBaseInitTypeDef TIM_TimeBaseinitstructure;TIM_TimeBaseinitstructure.TIM_ClockDivisionTIM_ClockDivision;TIM_TimeBaseinitstructure.TIM_CounterModeTIM_CounterMode;TIM_TimeBaseinitstructure.TIM_PeriodARR;TIM_TimeBaseinitstructure.TIM_PrescalerPSC;TIM_TimeBaseinitstructure.TIM_RepetitionCounterTIM_RepetitionCounter;TIM_TimeBaseInit(TIMX,TIM_TimeBaseinitstructure);}说明该函数把时钟使能、内部时钟配置、时基初始化全部封装好只需传入 ARR 和 PSC 即可确定定时周期。配合timer_init_CLeaR(TIMX, TIM_IT_Update)清除标志并开启更新中断即可实现定时中断功能。4.2 PWM 输出与动态调节/** * 函 数PWM输出开启配置 * 参 数TIM_OCMode - 输出比较模式如TIM_OCMode_PWM1 * 参 数TIM_OCPolarity - 输出极性如TIM_OCPolarity_High * 参 数CCR - 捕获/比较寄存器初始值占空比 * 参 数TIMX - 定时器指针 * 返 回 值无 */voidPWEL_OPEN(uint16_tTIM_OCMode,uint16_tTIM_OCPolarity,intCCR,TIM_TypeDef*TIMX){TIM_OCInitTypeDef a;TIM_OCStructInit(a);a.TIM_OCModeTIM_OCMode;a.TIM_OCPolarityTIM_OCPolarity;a.TIM_OutputStateTIM_OutputState_Enable;a.TIM_PulseCCR;TIM_OC1Init(TIMX,a);TIM_Cmd(TIMX,ENABLE);}/** * 函 数PWM占空比动态设置修改CCR * 参 数TIMX - 定时器指针 * 参 数Compare - 比较值占空比 Compare / (ARR1) * 返 回 值无 */voidPWM_CCR(TIM_TypeDef*TIMX,uint16_tCompare){TIM_SetCompare1(TIMX,Compare);}说明PWEL_OPEN完成 PWM 通道1的开启PWM_CCR可在运行中动态修改占空比非常适合电机调速、舵机角度控制等场景。另有PWM_PSC(TIMx, Prescaler, TIM_PSCReloadMode)用于动态修改预分频值timer_outAPB1支持外部时钟ETR模式timer_init_APB1_ENCODER用于编码器计数场景。调用示例示例代码后续将随资源包更新补充// 初始化TIM272MHz / (72-1) / (1000-1) ≈ 1kHz 溢出频率timer_init_APB1_in(RCC_APB1Periph_TIM2,TIM2,TIM_CKD_DIV1,TIM_CounterMode_Up,1000-1,72-1,0);// 开启PWM1模式初始占空比50%PWEL_OPEN(TIM_OCMode_PWM1,TIM_OCPolarity_High,500,TIM2);// 运行中动态调整占空比到25%PWM_CCR(TIM2,250);5. 输入捕获驱动封装输入捕获常用于测量外部信号的频率和占空比。这里以 TIM3 为例封装了初始化、从模式触发和读取函数。5.1 输入捕获初始化/** * 函 数输入捕获初始化配置 * 参 数TIMx - 定时器指针如TIM3 * 参 数TIM_Channel - 捕获通道如TIM_Channel_1 * 参 数TIM_ICFilter - 输入捕获滤波器值 * 参 数TIM_ICPolarity - 捕获极性如TIM_ICPolarity_Rising * 参 数TIM_ICPrescaler - 捕获预分频 * 参 数TIM_ICSelection - 输入通道映射选择 * 参 数j - 模式选择0普通输入捕获1PWM输入模式 * 返 回 值无 */voidic_init(TIM_TypeDef*TIMx,uint16_tTIM_Channel,intTIM_ICFilter,uint16_tTIM_ICPolarity,uint16_tTIM_ICPrescaler,uint16_tTIM_ICSelection,intj){TIM_ICInitTypeDef a;a.TIM_ChannelTIM_Channel;a.TIM_ICFilterTIM_ICFilter;a.TIM_ICPolarityTIM_ICPolarity;a.TIM_ICPrescalerTIM_ICPrescaler;a.TIM_ICSelectionTIM_ICSelection;TIM_ICInit(TIMx,a);if(j1){TIM_PWMIConfig(TIMx,a);// PWM输入模式自动配置双通道}}说明j1时使用PWM输入模式可同时测量周期和脉宽。5.2 其他输入捕获封装函数IC_RES(TIMx, TIM_InputTriggerSource, TIM_SlaveMode)配置从模式触发源并启动定时器。IC_GetFreq()返回频率值Hz公式1MHz / (CCR1)。IC_Getduty()返回占空比0~100%基于 CCR2 脉宽与 CCR1 周期计算。调用示例示例代码后续将随资源包更新补充// 初始化TIM3_CH1输入捕获上升沿触发普通模式ic_init(TIM3,TIM_Channel_1,0xF,TIM_ICPolarity_Rising,TIM_ICPSC_DIV1,TIM_ICSelection_DirectTI,0);// 配置从模式触发并启动定时器IC_RES(TIM3,TIM_TS_TI1FP1,TIM_SlaveMode_Reset);// 主循环中读取频率和占空比uint32_tfreqIC_GetFreq();// 频率单位Hzuint32_tdutyIC_Getduty();// 占空比0~100%注意以上读取函数硬编码了 TIM3若需移植到其他定时器请将TIM3替换为对应的定时器指针。6. ADC 驱动封装ADC模数转换器用于将模拟电压转换为数字量是传感器采集的核心外设。这里以 ADC1 为例封装了规则组初始化、校准、单次转换和多次采样取平均等函数。6.1 ADC 规则组初始化/** * 函 数ADC规则组通道初始化配置 * 参 数RCC_APB2Periph_ADCX - ADC外设时钟如RCC_APB2Periph_ADC1 * 参 数RCC_PCLK2 - ADC时钟分频配置如RCC_PCLK2_Div6 * 参 数ADCx - ADC指针如ADC1 * 参 数ADC_Channel - ADC通道号 * 参 数Rank - 规则组排序位置 * 参 数ADC_SampleTime - 采样时间 * 参 数ADC_Mode - ADC工作模式 * 参 数ADC_DataAlign - 数据对齐方式 * 参 数ADC_ExternalTrigConv - 外部触发转换源 * 参 数ADC_NbrOfChannel - 规则组通道总数 * 参 数ADC_ContinuousConvMode - 连续转换模式 * 参 数ADC_ScanConvMode - 扫描模式 * 返 回 值无 */voidAD_init_Regular(uint32_tRCC_APB2Periph_ADCX,uint32_tRCC_PCLK2,ADC_TypeDef*ADCx,uint8_tADC_Channel,uint8_tRank,uint8_tADC_SampleTime,uint32_tADC_Mode,uint32_tADC_DataAlign,uint32_tADC_ExternalTrigConv,intADC_NbrOfChannel,uint32_tADC_ContinuousConvMode,uint32_tADC_ScanConvMode){RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADCX,ENABLE);RCC_ADCCLKConfig(RCC_PCLK2);ADC_RegularChannelConfig(ADCx,ADC_Channel,Rank,ADC_SampleTime);ADC_InitTypeDef A;A.ADC_ContinuousConvModeADC_ContinuousConvMode;A.ADC_DataAlignADC_DataAlign;A.ADC_ExternalTrigConvADC_ExternalTrigConv;A.ADC_ModeADC_Mode;A.ADC_NbrOfChannelADC_NbrOfChannel;A.ADC_ScanConvModeADC_ScanConvMode;ADC_Init(ADCx,A);ADC_Cmd(ADCx,ENABLE);}说明该函数将时钟、通道、采样时间、工作模式等全部参数化。若需采集多个通道需在ADC_RegularChannelConfig中依次配置各通道的排序位置。6.2 其他 ADC 封装函数adc_Calibrate(ADCx)上电后建议先执行校准可有效消除ADC内部的偏移误差提升转换精度。AD_num(ADCx, ADC_FLAG)软件触发单次转换返回12位原始值0~4095。V_num(ADCx, ADC_FLAG)将原始值换算为放大100倍的电压值如330表示3.30V便于显示或串口打印。AD_avenum(ADCx, ADC_FLAG, a)对同一通道连续采样a次并取平均可有效抑制随机噪声适合对精度要求较高的传感器采集场景。调用示例示例代码后续将随资源包更新补充// 初始化ADC1通道0PA0采样时间55.5周期AD_init_Regular(RCC_APB2Periph_ADC1,RCC_PCLK2_Div6,ADC1,ADC_Channel_0,1,ADC_SampleTime_55Cycles5,ADC_Mode_Independent,ADC_DataAlign_Right,ADC_ExternalTrigConv_None,1,DISABLE,DISABLE);// 上电校准adc_Calibrate(ADC1);// 单次读取原始值和电压值uint16_trawAD_num(ADC1,ADC_FLAG_EOC);// 原始值 0~4095uint16_tvoltV_num(ADC1,ADC_FLAG_EOC);// 电压值如330表示3.30V// 多次采样取平均采样10次uint16_tavgAD_avenum(ADC1,ADC_FLAG_EOC,10);7. DMA 驱动封装DMA直接存储器访问可在不占用CPU的情况下完成外设与存储器之间的数据搬运常用于ADC连续采集、串口收发等场景。这里封装了DMA通道初始化和单次传输等待完成两个函数。7.1 DMA 通道初始化/** * 函 数DMA通道初始化配置 * 参 数RCC_AHBPeriph - AHB外设时钟如RCC_AHBPeriph_DMA1 * 参 数DMA_PeripheralBaseAddr - 外设基地址 * 参 数DMA_PeripheralDataSize - 外设数据宽度如DMA_PeripheralDataSize_Byte * 参 数DMA_PeripheralInc - 外设地址是否自增如DMA_PeripheralInc_Enable * 参 数DMA_BufferSize - 传输数据量缓冲区大小 * 参 数DMA_MemoryBaseAddr - 存储器基地址 * 参 数DMA_MemoryDataSize - 存储器数据宽度 * 参 数DMA_MemoryInc - 存储器地址是否自增 * 参 数DMA_DIR - 传输方向如DMA_DIR_PeripheralDST / DMA_DIR_PeripheralSRC * 参 数DMA_M2M - 存储器到存储器模式使能 * 参 数DMA_Mode - 工作模式如DMA_Mode_Normal / DMA_Mode_Circular * 参 数DMA_Priority - 通道优先级 * 参 数DMAy_Channelx - DMA通道指针如DMA1_Channel1 * 返 回 值无 */voidDMA_inT(uint32_tRCC_AHBPeriph,uint32_tDMA_PeripheralBaseAddr,uint32_tDMA_PeripheralDataSize,uint32_tDMA_PeripheralInc,uint32_tDMA_BufferSize,uint32_tDMA_MemoryBaseAddr,uint32_tDMA_MemoryDataSize,uint32_tDMA_MemoryInc,uint32_tDMA_DIR,uint32_tDMA_M2M,uint32_tDMA_Mode,uint32_tDMA_Priority,DMA_Channel_TypeDef*DMAy_Channelx){RCC_AHBPeriphClockCmd(RCC_AHBPeriph,ENABLE);DMA_InitTypeDef a;a.DMA_PeripheralBaseAddrDMA_PeripheralBaseAddr;a.DMA_PeripheralDataSizeDMA_PeripheralDataSize;a.DMA_PeripheralIncDMA_PeripheralInc;a.DMA_BufferSizeDMA_BufferSize;a.DMA_MemoryBaseAddrDMA_MemoryBaseAddr;a.DMA_MemoryDataSizeDMA_MemoryDataSize;a.DMA_MemoryIncDMA_MemoryInc;a.DMA_DIRDMA_DIR;a.DMA_M2MDMA_M2M;a.DMA_ModeDMA_Mode;a.DMA_PriorityDMA_Priority;DMA_Init(DMAy_Channelx,a);DMA_Cmd(DMAy_Channelx,ENABLE);}说明该函数将DMA的时钟、地址、数据宽度、方向、模式、优先级等全部参数化一次调用即可完成通道配置并启动。7.2 DMA 单次传输并等待完成DMA_TRANFER(DMAy_Channelx, DataNumber, DMAy_FLAG)完成一次完整的单次传输流程先关闭DMA、设置本次传输的数据量、重新开启、等待传输完成标志置位最后清除标志。适合需要精确控制每次传输数据量的场景。调用示例示例代码后续将随资源包更新补充// 初始化DMA1通道1外设到内存字节宽度普通模式DMA_inT(RCC_AHBPeriph_DMA1,(uint32_t)ADC1-DR,// 外设基地址ADC1数据寄存器DMA_PeripheralDataSize_Byte,DMA_PeripheralInc_Disable,4,// 缓冲区大小4字节(uint32_t)adc_buffer,// 存储器基地址DMA_MemoryDataSize_Byte,DMA_MemoryInc_Enable,DMA_DIR_PeripheralSRC,// 外设→内存DMA_M2M_Disable,DMA_Mode_Normal,DMA_Priority_High,DMA1_Channel1);// 启动一次传输并等待完成DMA_TRANFER(DMA1_Channel1,4,DMA1_FLAG_TC1);8. 编码器接口驱动封装编码器接口用于读取正交编码器的转速和方向常用于电机测速。新手只需调用初始化函数并读取计数值即可无需理解正交解码的底层原理。encoder(TIMx, TIM_EncoderMode, TIM_IC1Polarity, TIM_IC2Polarity)初始化编码器接口并启动定时器。encoder_get(TIMx)返回有符号16位计数值正转递增反转递减。调用示例示例代码后续将随资源包更新补充// 初始化TIM2编码器接口TI1TI2双边沿计数encoder(TIM2,TIM_EncoderMode_TI12,TIM_ICPolarity_Rising,TIM_ICPolarity_Rising);// 主循环中读取当前计数值int16_tcountencoder_get(TIM2);if(count0){// 正转}elseif(count0){// 反转}8. 总结本文通过封装 GPIO、输入捕获、编码器接口、ADC 和 DMA展示了如何用函数化思维简化 STM32 外设操作。这套封装特别适合新手具有以下优点参数化端口、引脚、模式、通道、地址等均作为参数传入灵活适配不同硬件。防漏配置时钟使能、初始化、模式设置等关键步骤全部封装在函数内部新手按注释填参即可不会漏写指令。可复用一次封装多处调用减少重复代码。易维护修改外设配置只需调整调用参数无需改动驱动内部逻辑。后续将持续补充 SPI、I2C、看门狗等更多外设的简易配置。读者可根据实际项目需求在此基础上逐步构建属于自己的 STM32 快速开发库。资源获取本文配套工程代码已打包为stm32_1.zip可通过夸克网盘下载链接https://pan.quark.cn/s/95809e5ce13b?pwdGjmb提取码Gjmb打开「夸克网盘APP」复制链接或输入提取码即可获取。下载后可直接导入 Keil 工程对照本文各章节函数进行调用练习。
返回列表