stm32 固件库函数介绍

1、RCC

1
2
3
void RCC_AHBPeriphClockCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState);
void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);
void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);

2、GPIO 相关函数

1
2
3
4
5
6
7
void GPIO_AFIODeInit(void);							// 复位AFIO外设
void GPIO_PinLockConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); // 锁定 GPIO 配置
void GPIO_EventOutputConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource); // 配置AFIO事件输出功能
void GPIO_EventOutputCmd(FunctionalState NewState); // 配置AFIO事件输出功能
void GPIO_PinRemapConfig(uint32_t GPIO_Remap, FunctionalState NewState); // 进行引脚重映射
void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource); // 配置AFIO的数据选择器
void GPIO_ETH_MediaInterfaceConfig(uint32_t GPIO_ETH_MediaInterface); // 与以太网有关

3、EXTI 相关函数

1
2
3
4
5
6
7
8
void EXTI_DeInit(void);					// 清除 EXTI 配置
void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct); // 初始化 EXTI
void EXTI_StructInit(EXTI_InitTypeDef* EXTI_InitStruct);// 给EXTI结构体赋默认值
void EXTI_GenerateSWInterrupt(uint32_t EXTI_Line); // 软件触发EXTI外部中断
FlagStatus EXTI_GetFlagStatus(uint32_t EXTI_Line); // 获取标志位
void EXTI_ClearFlag(uint32_t EXTI_Line); // 清空标志位
ITStatus EXTI_GetITStatus(uint32_t EXTI_Line); // 获取中断标志位
void EXTI_ClearITPendingBit(uint32_t EXTI_Line); // 清空中断标志位

4、中断向量表

中断向量表位于启动文件(start/startup_stm32f10x.md.s)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
__Vectors       DCD     __initial_sp               ; Top of Stack
DCD Reset_Handler ; Reset Handler
DCD NMI_Handler ; NMI Handler
DCD HardFault_Handler ; Hard Fault Handler
DCD MemManage_Handler ; MPU Fault Handler
DCD BusFault_Handler ; Bus Fault Handler
DCD UsageFault_Handler ; Usage Fault Handler
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD SVC_Handler ; SVCall Handler
DCD DebugMon_Handler ; Debug Monitor Handler
DCD 0 ; Reserved
DCD PendSV_Handler ; PendSV Handler
DCD SysTick_Handler ; SysTick Handler

; External Interrupts
DCD WWDG_IRQHandler ; Window Watchdog
DCD PVD_IRQHandler ; PVD through EXTI Line detect
DCD TAMPER_IRQHandler ; Tamper
DCD RTC_IRQHandler ; RTC
DCD FLASH_IRQHandler ; Flash
DCD RCC_IRQHandler ; RCC
DCD EXTI0_IRQHandler ; EXTI Line 0
DCD EXTI1_IRQHandler ; EXTI Line 1
DCD EXTI2_IRQHandler ; EXTI Line 2
DCD EXTI3_IRQHandler ; EXTI Line 3
DCD EXTI4_IRQHandler ; EXTI Line 4
DCD DMA1_Channel1_IRQHandler ; DMA1 Channel 1
DCD DMA1_Channel2_IRQHandler ; DMA1 Channel 2
DCD DMA1_Channel3_IRQHandler ; DMA1 Channel 3
DCD DMA1_Channel4_IRQHandler ; DMA1 Channel 4
DCD DMA1_Channel5_IRQHandler ; DMA1 Channel 5
DCD DMA1_Channel6_IRQHandler ; DMA1 Channel 6
DCD DMA1_Channel7_IRQHandler ; DMA1 Channel 7
DCD ADC1_2_IRQHandler ; ADC1_2
DCD USB_HP_CAN1_TX_IRQHandler ; USB High Priority or CAN1 TX
DCD USB_LP_CAN1_RX0_IRQHandler ; USB Low Priority or CAN1 RX0
DCD CAN1_RX1_IRQHandler ; CAN1 RX1
DCD CAN1_SCE_IRQHandler ; CAN1 SCE
DCD EXTI9_5_IRQHandler ; EXTI Line 9..5
DCD TIM1_BRK_IRQHandler ; TIM1 Break
DCD TIM1_UP_IRQHandler ; TIM1 Update
DCD TIM1_TRG_COM_IRQHandler ; TIM1 Trigger and Commutation
DCD TIM1_CC_IRQHandler ; TIM1 Capture Compare
DCD TIM2_IRQHandler ; TIM2
DCD TIM3_IRQHandler ; TIM3
DCD TIM4_IRQHandler ; TIM4
DCD I2C1_EV_IRQHandler ; I2C1 Event
DCD I2C1_ER_IRQHandler ; I2C1 Error
DCD I2C2_EV_IRQHandler ; I2C2 Event
DCD I2C2_ER_IRQHandler ; I2C2 Error
DCD SPI1_IRQHandler ; SPI1
DCD SPI2_IRQHandler ; SPI2
DCD USART1_IRQHandler ; USART1
DCD USART2_IRQHandler ; USART2
DCD USART3_IRQHandler ; USART3
DCD EXTI15_10_IRQHandler ; EXTI Line 15..10
DCD RTCAlarm_IRQHandler ; RTC Alarm through EXTI Line
DCD USBWakeUp_IRQHandler ; USB Wakeup from suspend
__Vectors_End

5、NVIC 相关函数

1
2
3
4
5
6
/* 注意:中断分支整个项目只能进行一次 */
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup); // 中断分组

void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct); // 初始化 NVIC
void NVIC_SetVectorTable(uint32_t NVIC_VectTab, uint32_t Offset); // 设置中断向量表
void NVIC_SystemLPConfig(uint8_t LowPowerMode, FunctionalState NewState); // 系统低功耗配置

6、TIM 相关函数

基本函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/* 初始化配置 */
void TIM_DeInit(TIM_TypeDef* TIMx); // 恢复缺省配置
void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct); // 时基单元初始化

void TIM_TimeBaseStructInit(TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct); // 时基单元结构体变量赋默认值

void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState); // 使能计数器

void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState); // 使能中断输出信号

void TIM_InternalClockConfig(TIM_TypeDef* TIMx); // 选择内部时钟
void TIM_ITRxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource); // 选择其他定时器的时钟
void TIM_TIxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_TIxExternalCLKSource,
uint16_t TIM_ICPolarity, uint16_t ICFilter); // 选择TIx捕获通道的时钟
void TIM_ETRClockMode1Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,
uint16_t ExtTRGFilter); // 选择 ETR 通过外部时钟模式1输入的时钟
void TIM_ETRClockMode2Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler,
uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter); // 选择 ETR 通过外部时钟模式2输入的时钟
void TIM_ETRConfig(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,
uint16_t ExtTRGFilter); // 配置 ETR 预分频器、极性、滤波器等参数

/* 更改参数 */
void TIM_PrescalerConfig(TIM_TypeDef* TIMx, uint16_t Prescaler, uint16_t TIM_PSCReloadMode); // 更改预分频值
void TIM_CounterModeConfig(TIM_TypeDef* TIMx, uint16_t TIM_CounterMode); // 改变计数模式
void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState); // 改变计数器的预装功能设置
void TIM_SetCounter(TIM_TypeDef* TIMx, uint16_t Counter); // 给计数器写入值
void TIM_SetAutoreload(TIM_TypeDef* TIMx, uint16_t Autoreload); // 给自动重装器写入值
uint16_t TIM_GetCounter(TIM_TypeDef* TIMx); // 获取当前计数器的值
uint16_t TIM_GetPrescaler(TIM_TypeDef* TIMx); // 获取当前预分频的值

/* 获取与清除标志位 */
FlagStatus TIM_GetFlagStatus(TIM_TypeDef* TIMx, uint16_t TIM_FLAG); // 获取标志位
void TIM_ClearFlag(TIM_TypeDef* TIMx, uint16_t TIM_FLAG); // 清空标志位
ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t TIM_IT); // 获取中断标志位
void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT); // 清空中断标志位

输出比较函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
void TIM_OC1Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);	// 配置输出比较模块
void TIM_OC2Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct); // 配置输出比较模块
void TIM_OC3Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct); // 配置输出比较模块
void TIM_OC4Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct); // 配置输出比较模块
void TIM_OCStructInit(TIM_OCInitTypeDef* TIM_OCInitStruct); // 输出结构体赋默认值
void TIM_ForcedOC1Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction); // 配置强制输出模式,强制输出高电平或低电平
void TIM_ForcedOC2Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction); // 配置强制输出模式,强制输出高电平或低电平
void TIM_ForcedOC3Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction); // 配置强制输出模式,强制输出高电平或低电平
void TIM_ForcedOC4Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction); // 配置强制输出模式,强制输出高电平或低电平
void TIM_OC1PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload); // 配置 CCR 预装值功能
void TIM_OC2PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload); // 配置 CCR 预装值功能
void TIM_OC3PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload); // 配置 CCR 预装值功能
void TIM_OC4PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload); // 配置 CCR 预装值功能
void TIM_OC1FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast); // 配置快速使能
void TIM_OC2FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast); // 配置快速使能
void TIM_OC3FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast); // 配置快速使能
void TIM_OC4FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast); // 配置快速使能
void TIM_ClearOC1Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear); // 外部事件时清除 REF 信号
void TIM_ClearOC2Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear); // 外部事件时清除 REF 信号
void TIM_ClearOC3Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear); // 外部事件时清除 REF 信号
void TIM_ClearOC4Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear); // 外部事件时清除 REF 信号
void TIM_OC1PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity); // 设置输出比较的极性
void TIM_OC1NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity); // 设置输出比较的极性(互补通道
void TIM_OC2PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity); // 设置输出比较的极性
void TIM_OC2NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity); // 设置输出比较的极性(互补通道
void TIM_OC3PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity); // 设置输出比较的极性
void TIM_OC3NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity); // 设置输出比较的极性(互补通道
void TIM_OC4PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity); // 设置输出比较的极性
void TIM_CCxCmd(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_CCx); // 修改输出使能
void TIM_CCxNCmd(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_CCxN); // 修改输出使能
void TIM_SelectOCxM(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_OCMode);// 修改输出比较模式
void TIM_SetCompare1(TIM_TypeDef* TIMx, uint16_t Compare1); // 更改 CCR 寄存器的值
void TIM_SetCompare2(TIM_TypeDef* TIMx, uint16_t Compare2); // 更改 CCR 寄存器的值
void TIM_SetCompare3(TIM_TypeDef* TIMx, uint16_t Compare3); // 更改 CCR 寄存器的值
void TIM_SetCompare4(TIM_TypeDef* TIMx, uint16_t Compare4); // 更改 CCR 寄存器的值

输入捕获函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void TIM_ICInit(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct);	// 输入捕获单元初始化
void TIM_PWMIConfig(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct); // 初始化输入捕获单元,快速配置两个通道,配置为PWMI模式
void TIM_ICStructInit(TIM_ICInitTypeDef* TIM_ICInitStruct);// 输入捕获结构体赋默认值
void TIM_SelectInputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource); // 选择输入触发源(从模式的触发源)
void TIM_SelectOutputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_TRGOSource); // 选择输出触发源TRGO(主模式输出)
void TIM_SelectSlaveMode(TIM_TypeDef* TIMx, uint16_t TIM_SlaveMode); // 选择从模式
void TIM_SetIC1Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC); // 配置1通道的分频器
void TIM_SetIC2Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC); // 配置2通道的分频器
void TIM_SetIC3Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC); // 配置3通道的分频器
void TIM_SetIC4Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC); // 配置4通道的分频器
void TIM_SetClockDivision(TIM_TypeDef* TIMx, uint16_t TIM_CKD);
uint16_t TIM_GetCapture1(TIM_TypeDef* TIMx); // 读取1通道的CCR
uint16_t TIM_GetCapture2(TIM_TypeDef* TIMx); // 读取2通道的CCR
uint16_t TIM_GetCapture3(TIM_TypeDef* TIMx); // 读取3通道的CCR
uint16_t TIM_GetCapture4(TIM_TypeDef* TIMx); // 读取4通道的CCR

编码器接口函数:

1
2
void TIM_EncoderInterfaceConfig(TIM_TypeDef* TIMx, uint16_t TIM_EncoderMode,
uint16_t TIM_IC1Polarity, uint16_t TIM_IC2Polarity); // 编码器接口配置

7、ADC相关函数

1
void RCC_ADCCLKConfig(uint32_t RCC_PCLK2);	// 配置 ADC_CLK 分频器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
void ADC_DeInit(ADC_TypeDef* ADCx);							// 恢复缺省配置
void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct); // 初始化 ADC
void ADC_StructInit(ADC_InitTypeDef* ADC_InitStruct); // ADC结构体初始化
void ADC_Cmd(ADC_TypeDef* ADCx, FunctionalState NewState); // 开启 ADC
void ADC_DMACmd(ADC_TypeDef* ADCx, FunctionalState NewState); // 开启 DMA 输出信号
void ADC_ITConfig(ADC_TypeDef* ADCx, uint16_t ADC_IT, FunctionalState NewState); // 中断输出控制
void ADC_SoftwareStartConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState); // 软件触发 ADC
FlagStatus ADC_GetSoftwareStartConvStatus(ADC_TypeDef* ADCx); // 获取软件开始转换状态(软件触发后立刻从1清零)(一般不用)
void ADC_DiscModeChannelCountConfig(ADC_TypeDef* ADCx, uint8_t Number); // 配置每隔几个通道间断一次
void ADC_DiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState); // 启用间断模式
void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime); // ADC规则组通道配置
void ADC_ExternalTrigConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState); // ADC 外部触发转换控制
uint16_t ADC_GetConversionValue(ADC_TypeDef* ADCx); // ADC 获取转换值
uint32_t ADC_GetDualModeConversionValue(void); // ADC 获取双模式转换值

/* 校准相关配置 */
void ADC_ResetCalibration(ADC_TypeDef* ADCx); // 复位校准
FlagStatus ADC_GetResetCalibrationStatus(ADC_TypeDef* ADCx); // 获取复位校准状态
void ADC_StartCalibration(ADC_TypeDef* ADCx); // 开始校准
FlagStatus ADC_GetCalibrationStatus(ADC_TypeDef* ADCx); // 获取开始校准状态

/* 注入组相关配置 */
void ADC_AutoInjectedConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
void ADC_InjectedDiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
void ADC_ExternalTrigInjectedConvConfig(ADC_TypeDef* ADCx, uint32_t ADC_ExternalTrigInjecConv);
void ADC_ExternalTrigInjectedConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
void ADC_SoftwareStartInjectedConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
FlagStatus ADC_GetSoftwareStartInjectedConvCmdStatus(ADC_TypeDef* ADCx);
void ADC_InjectedChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime);
void ADC_InjectedSequencerLengthConfig(ADC_TypeDef* ADCx, uint8_t Length);
void ADC_SetInjectedOffset(ADC_TypeDef* ADCx, uint8_t ADC_InjectedChannel, uint16_t Offset);
uint16_t ADC_GetInjectedConversionValue(ADC_TypeDef* ADCx, uint8_t ADC_InjectedChannel);

/* 模拟看门狗相关配置 */
void ADC_AnalogWatchdogCmd(ADC_TypeDef* ADCx, uint32_t ADC_AnalogWatchdog); // 是否启动模拟看门狗
void ADC_AnalogWatchdogThresholdsConfig(ADC_TypeDef* ADCx, uint16_t HighThreshold, uint16_t LowThreshold); // 配置高低阈值
void ADC_AnalogWatchdogSingleChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel); // 配置看门通道

void ADC_TempSensorVrefintCmd(FunctionalState NewState); // ADC 温度传感器,内部电压控制

FlagStatus ADC_GetFlagStatus(ADC_TypeDef* ADCx, uint8_t ADC_FLAG); // 获取标志位状态
void ADC_ClearFlag(ADC_TypeDef* ADCx, uint8_t ADC_FLAG); // 清空标志位
ITStatus ADC_GetITStatus(ADC_TypeDef* ADCx, uint16_t ADC_IT); // 获取中断状态
void ADC_ClearITPendingBit(ADC_TypeDef* ADCx, uint16_t ADC_IT); // 清空中断挂起位

8、DMA 相关函数

1
2
3
4
5
6
7
8
9
10
11
12
13
void DMA_DeInit(DMA_Channel_TypeDef* DMAy_Channelx);							// 恢复缺省配置
void DMA_Init(DMA_Channel_TypeDef* DMAy_Channelx, DMA_InitTypeDef* DMA_InitStruct); // 初始化 DMA
void DMA_StructInit(DMA_InitTypeDef* DMA_InitStruct); // DMA 结构体初始化
void DMA_Cmd(DMA_Channel_TypeDef* DMAy_Channelx, FunctionalState NewState); // 使能 DMA
void DMA_ITConfig(DMA_Channel_TypeDef* DMAy_Channelx, uint32_t DMA_IT, FunctionalState NewState); // 中断输出使能

void DMA_SetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx, uint16_t DataNumber); // DMA 设置当前数据寄存器
uint16_t DMA_GetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx); // DMA 获取当前数据寄存器

FlagStatus DMA_GetFlagStatus(uint32_t DMAy_FLAG); // 获取标志位状态
void DMA_ClearFlag(uint32_t DMAy_FLAG); // 清空标志位
ITStatus DMA_GetITStatus(uint32_t DMAy_IT); // 获取中断状态
void DMA_ClearITPendingBit(uint32_t DMAy_IT); // 清空中断挂起位

9、USART

1
2
3
4
5
6
7
8
9
10
11
12
13
14
void USART_DeInit(USART_TypeDef* USARTx);							// 恢复缺省配置
void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct); // 初始化 USART
void USART_StructInit(USART_InitTypeDef* USART_InitStruct); // USART 结构体初始化
void USART_ClockInit(USART_TypeDef* USARTx, USART_ClockInitTypeDef* USART_ClockInitStruct); // 配置同步时钟输出
void USART_ClockStructInit(USART_ClockInitTypeDef* USART_ClockInitStruct); // 同步时钟输出结构体初始化
void USART_Cmd(USART_TypeDef* USARTx, FunctionalState NewState); // 开启 USART
void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT, FunctionalState NewState); // 开启中断
void USART_DMACmd(USART_TypeDef* USARTx, uint16_t USART_DMAReq, FunctionalState NewState); // 开启USART到DMA的触发通道
void USART_SendData(USART_TypeDef* USARTx, uint16_t Data); // 发送数据
uint16_t USART_ReceiveData(USART_TypeDef* USARTx); // 接收数据
FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG); // 获取标志位状态
void USART_ClearFlag(USART_TypeDef* USARTx, uint16_t USART_FLAG); // 清空标志位
ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT); // 获取中断状态
void USART_ClearITPendingBit(USART_TypeDef* USARTx, uint16_t USART_IT); // 清空中断挂起位

基础模块设计

GPIO

具体步骤

  • RCC 开启时钟
  • GPIO_Init() 初始化 GPIO
  • 使用输出或输入函数控制 GPIO
1
2
3
4
5
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //GPIO_Pin_15;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);

EXTI 外部中断

EXTI基本结构

具体步骤

  • RCC 开启时钟(GPIO、AFIO)
  • 配置 GPIO 为输入模式
  • 配置 AFIO,选择我们使用的一路GPIO
  • 配置 EXTI,选择边沿触发方式、触发响应方式(中断响应、事件响应)
  • 配置 NVIC,选择优先级
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
void CountSensor_Init(void)
{
/* RCC 开启时钟 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);

/* 配置 GPIO */
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);

/* 配置 AFIO */
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource14);

/* 配置 EXTI */
EXTI_InitTypeDef EXTI_InitStructure;
EXTI_InitStructure.EXTI_Line = EXTI_Line14;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_Init(&EXTI_InitStructure);

/* 配置 NVIC,中断分组 */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

/* 配置 NVIC,设置优先级 */
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_Init(&NVIC_InitStructure);
}

void EXTI15_10_IRQHandler(void)
{
if (EXTI_GetITStatus(EXTI_Line14) == SET)
{

EXTI_ClearITPendingBit(EXTI_Line14);
}
}

EXTI 与 NVIC 的时钟不需手动开启

Timer 定时中断

定时中断基本结构

  • 具体步骤

    • RCC 开启时钟
    • 选择时基单元的时钟源(定时中断选择内部时钟源)
    • 配置时基单元
    • 配置输出中断控制,允许更新中断到 NVIC
    • 配置 NVIC,打开定时器中断通道,分配优先级
    • 运行控制
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
void Timer_Init(void)
{

/* RCC 开启时钟 */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

/* 选择时基单元的时钟源,内部时钟源 */
TIM_InternalClockConfig(TIM2);

/* 配置时基单元 */
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_Period = 10000 - 1;
TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1;
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);

TIM_ClearFlag(TIM2, TIM_FLAG_Update);
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); // 使能中断

/* 配置 NVIC,中断分组 */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

/* 配置 NVIC,配置优先级 */
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_Init(&NVIC_InitStructure);

/* 启动计时器 */
TIM_Cmd(TIM2, ENABLE);
}

void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
{

TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
}
}

PWM 输出

PWM基本结构

  • 具体步骤
    • RCC 开启时钟
    • 配置时基单元
    • 配置输出比较单元
    • 配置 GPIO
    • 运行控制,启动计数器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include "stm32f10x.h"                  // Device header

void PWM_Init(void)
{
/* RCC 开启时钟 */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

/* 配置 GPIO */
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);

/* 选择时基单元的时钟源,内部时钟源 */
TIM_InternalClockConfig(TIM2);

/* 配置时基单元 */
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_Period = 100 - 1; //ARR
TIM_TimeBaseInitStructure.TIM_Prescaler = 36 - 1; //PSC
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);

/* 配置输出比较单元 */
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCStructInit(&TIM_OCInitStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 0; //CCR
TIM_OC3Init(TIM2, &TIM_OCInitStructure);

/* 运行控制,启动计数器 */
TIM_Cmd(TIM2, ENABLE);
}

// 设置占空比
void PWM_SetCompare3(uint16_t Compare)
{
TIM_SetCompare3(TIM2, Compare);
}

// 设置预分频值
void PWM_SetPrescaler(uint16_t Prescaler)
{
TIM_PrescalerConfig(TIM2, Prescaler, TIM_PSCReloadMode_Immediate);
}

IC 输入捕获

输入捕获基本结构

主从触发模式

  • 具体步骤
    • RCC 开启时钟
    • GPIO 初始化为输入模式(上拉或浮空)
    • 配置时基单元
    • 配置输入捕获单元,包括滤波器、极性、直连通道还是交叉通道、分频器这些参数
    • 选择从模式的触发源(TI1FP1)
    • 选择触发后执行的操作(Reset操作)
    • 运行控制,启动计时器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include "stm32f10x.h"                  // Device header

void IC_Init(void)
{
/* RCC 开启时钟 */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

/* GPIO 初始化为输入模式(上拉或浮空) */
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);

/* 选择时基单元的时钟源,内部时钟源 */
TIM_InternalClockConfig(TIM3);

/* 配置时基单元 */
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_Period = 65536 - 1; //ARR
TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1; //PSC
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);

/* 配置输入捕获单元 */
TIM_ICInitTypeDef TIM_ICInitStructure;
TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
TIM_ICInitStructure.TIM_ICFilter = 0xF;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_ICInit(TIM3, &TIM_ICInitStructure);

/* 选择从模式的触发源,选择触发后执行的操作 */
TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1);
TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);

/* 运行控制,启动计时器 */
TIM_Cmd(TIM3, ENABLE);
}

uint32_t IC_GetFreq(void)
{
return 1000000 / (TIM_GetCapture1(TIM3) + 1);
}

PWMI 模式

PWMI基本结构

  • 具体步骤
    • RCC 开启时钟
    • GPIO 初始化为输入模式(上拉或浮空)
    • 配置时基单元
    • 配置输入捕获单元
    • 选择从模式的触发源(TI1FP1)
    • 选择触发后执行的操作(Reset操作)
    • 运行控制,启动计时器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include "stm32f10x.h"                  // Device header

void IC_Init(void)
{
/* RCC 开启时钟 */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

/* GPIO 初始化为输入模式(上拉或浮空) */
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);

/* 选择时基单元的时钟源,内部时钟源 */
TIM_InternalClockConfig(TIM3);

/* 配置时基单元 */
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_Period = 65536 - 1; //ARR
TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1; //PSC
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);

/* 配置输入捕获单元 */
TIM_ICInitTypeDef TIM_ICInitStructure;
TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
TIM_ICInitStructure.TIM_ICFilter = 0xF;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_PWMIConfig(TIM3, &TIM_ICInitStructure);

/* 选择从模式的触发源,选择触发后执行的操作 */
TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1);
TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);

/* 运行控制,启动计时器 */
TIM_Cmd(TIM3, ENABLE);
}

uint32_t IC_GetFreq(void)
{
return 1000000 / (TIM_GetCapture1(TIM3) + 1);
}

uint32_t IC_GetDuty(void)
{
return (TIM_GetCapture2(TIM3) + 1) * 100 / (TIM_GetCapture1(TIM3) + 1);
}

编码器接口测速

编码器接口基本结构

  • 具体步骤
    • RCC 开启时钟
    • GPIO 初始化为输入模式
    • 配置时基单元
    • 配置输入捕获单元,包括滤波器、极性参数
    • 配置编码器接口模式
    • 运行控制,启动计时器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include "stm32f10x.h"                  // Device header

void Encoder_Init(void)
{
/* RCC 开启时钟 */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

/* GPIO 初始化为输入模式 */
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);

/* 配置时基单元 */
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; // 没用
TIM_TimeBaseInitStructure.TIM_Period = 65536 - 1; //ARR
TIM_TimeBaseInitStructure.TIM_Prescaler = 1 - 1; //PSC
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);

/* 配置输入捕获单元,包括滤波器、极性参数 */
TIM_ICInitTypeDef TIM_ICInitStructure;
TIM_ICStructInit(&TIM_ICInitStructure);
TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
TIM_ICInitStructure.TIM_ICFilter = 0xF;
TIM_ICInit(TIM3, &TIM_ICInitStructure);
TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
TIM_ICInitStructure.TIM_ICFilter = 0xF;
TIM_ICInit(TIM3, &TIM_ICInitStructure);

/* 配置编码器接口模式 */
TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);

/* 运行控制,启动计时器 */
TIM_Cmd(TIM3, ENABLE);
}

int16_t Encoder_Get(void)
{
int16_t Temp;
Temp = TIM_GetCounter(TIM3);
TIM_SetCounter(TIM3, 0);
return Temp;
}

ADC

ADC基本结构

  • 具体步骤
    • RCC 开启时钟(ADC和GPIO),配置 ADC_CLK 分频器
    • GPIO 配置为模拟输入模式
    • 配置多路开关
    • 配置 ADC 转换器
    • 配置看门狗(可选)
    • 开启中断,配置 NVIC(可选)
    • 开启 ADC
    • 对 ADC 进行校准(建议)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include "stm32f10x.h"                  // Device header

void AD_Init(void)
{
/* RCC 开启时钟 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

/* 配置 ADC_CLK 分频器 */
RCC_ADCCLKConfig(RCC_PCLK2_Div6);

/* GPIO 配置为模拟输入模式 */
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);

/* 配置多路开关 */
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);

/* 配置 ADC 转换器 */
ADC_InitTypeDef ADC_InitStructure;
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
ADC_InitStructure.ADC_NbrOfChannel = 1;
ADC_Init(ADC1, &ADC_InitStructure);

/* 开启 ADC */
ADC_Cmd(ADC1, ENABLE);

/* 对 ADC 进行校准 */
ADC_ResetCalibration(ADC1); // 复位校准
while (ADC_GetResetCalibrationStatus(ADC1) == SET); // 等待复位校准完成
ADC_StartCalibration(ADC1); // 开始校准
while (ADC_GetCalibrationStatus(ADC1) == SET); // 等待校准完成
}

uint16_t AD_GetValue(void)
{
ADC_SoftwareStartConvCmd(ADC1, ENABLE); // 软件触发转换
while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET); // 等待转换完成
return ADC_GetConversionValue(ADC1); // 读取 ADC 转换结果
}

DMA

DMA基本结构

  • 具体步骤
    • RCC 开启时钟
    • 初始化 DMA(包括外设和存储器的各个数据、方向、传输计数器、是否需要自动重装、选择触发源、通道优先级)
    • 若为硬件触发,开启对应 DMA 输出(可选)
    • 开启中断输出,配置 NVIC(可选)
    • 开启 DMA

改变传输寄存器时需先失能,写入值后再使能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include "stm32f10x.h"                  // Device header

uint16_t MyDMA_Size;

void MyDMA_Init(uint32_t AddrA, uint32_t AddrB, uint16_t Size)
{
MyDMA_Size = Size;

/* RCC 开启时钟 */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

/* 初始化 DMA */
DMA_InitTypeDef DMA_InitStructure;
DMA_InitStructure.DMA_PeripheralBaseAddr = AddrA; // 外设起始地址
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; // 外设数据宽度
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable; // 外设是否自增
DMA_InitStructure.DMA_MemoryBaseAddr = AddrB;; // 存储器起始地址
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;; // 存储器数据宽度
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;; // 存储器是否自增
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; // 传输方向
DMA_InitStructure.DMA_BufferSize = Size; // 缓冲区大小,即传输寄存器
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; // 传输模式,即是否使用自动重装
DMA_InitStructure.DMA_M2M = DMA_M2M_Enable; // 选择是否存储器到存储器,即选择硬件触发或软件触发
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; // 优先级
DMA_Init(DMA1_Channel1, &DMA_InitStructure);

/* 开启 DMA */
DMA_Cmd(DMA1_Channel1, DISABLE);
}

void MyDMA_Transfer(void)
{
/* DMA失能、设置当前数据寄存器、DMA使能 */
DMA_Cmd(DMA1_Channel1, DISABLE);
DMA_SetCurrDataCounter(DMA1_Channel1, MyDMA_Size);
DMA_Cmd(DMA1_Channel1, ENABLE);

/* 等待转运完成、清除转运完成标志位 */
while (DMA_GetFlagStatus(DMA1_FLAG_TC1) == RESET);
DMA_ClearFlag(DMA1_FLAG_TC1);
}

USART 串口

USART基本结构

  • 具体步骤
    • RCC 开启时钟(USART和GPIO)
    • GPIO设置(TX配置为复用输出、RX配置为输入)
    • 配置USART
    • 开启中断、配置NVIC(可选)
    • 开启USART
  1. 发送数据

初始化函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include "stm32f10x.h"                  // Device header
#include <stdio.h>
#include <stdarg.h>

void Serial_Init(void)
{
/* RCC 开启时钟 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

/* GPIO设置 */
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 复用推挽输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);

/* 配置USART */
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = 9600; // 波特率
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // 硬件流控制
USART_InitStructure.USART_Mode = USART_Mode_Tx; // 串口模式
USART_InitStructure.USART_Parity = USART_Parity_No; // 校验位
USART_InitStructure.USART_StopBits = USART_StopBits_1; // 停止位
USART_InitStructure.USART_WordLength = USART_WordLength_8b; // 字长
USART_Init(USART1, &USART_InitStructure);

/* 开启USART */
USART_Cmd(USART1, ENABLE);
}

相关函数封装:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
/**
* @brief 发送一个字节
* @param Byte: 要发送的字节数据
* @retval None
*/
void Serial_SendByte(uint8_t Byte)
{
USART_SendData(USART1, Byte);
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
}

/**
* @brief 发送一个数组
* @param Array: 数组的首地址,必须为 uint8_t 类型的数组
* @param Length: 数组的长度
* This parameter can be any combination of GPIO_Pin_x where x can be (0..15).
* @retval None
*/
void Serial_SendArray(uint8_t *Array, uint16_t Length)
{
uint16_t i;
for (i = 0; i < Length; i ++)
{
Serial_SendByte(Array[i]);
}
}

/**
* @brief 发送字符串
* @param String: 字符串的首地址
* @retval None
*/
void Serial_SendString(char *String)
{
uint8_t i;
for (i = 0; String[i] != '\0'; i ++)
{
Serial_SendByte(String[i]);
}
}

/**
* @brief 指数函数,即X的Y次方
* @param X:底数
* @param Y:指数
* @retval None
*/
uint32_t Serial_Pow(uint32_t X, uint32_t Y)
{
uint32_t Result = 1;
while (Y --)
{
Result *= X; // 1 乘以X Y次
}
return Result;
}

/**
* @brief 发送数字
* 本质将数字手动转为字符串然后发送
* @param Number
* @param Length
* @retval None
*/
void Serial_SendNumber(uint32_t Number, uint8_t Length)
{
uint8_t i;
for (i = 0; i < Length; i ++)
{
Serial_SendByte(Number / Serial_Pow(10, Length - i - 1) % 10 + '0'); // 发送Number的每一位(高位先行)'0'->偏移
}
}

/**
* @brief fputc重定向
* @param
* @retval
*/
int fputc(int ch, FILE *f)
{
Serial_SendByte(ch);
return ch;
}

/**
* @brief 模拟printf重写打印字符串函数
* @retval None
*/
void Serial_Printf(char *format, ...)
{
char String[100];
va_list arg;
va_start(arg, format);
vsprintf(String, format, arg);
va_end(arg);
Serial_SendString(String);
}

printf 重定向方法3:

1
2
3
char String[100];
sprintf(String, "\r\nNum3=%d", 333);
Serial_SendString(String);
  1. 接收数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include "stm32f10x.h"                  // Device header
#include <stdio.h>
#include <stdarg.h>

uint8_t Serial_RxData;
uint8_t Serial_RxFlag;

void Serial_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // 上拉输入
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);

USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_Init(USART1, &USART_InitStructure);

/* 开启中断 */
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);

/* NVIC 分组 */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

/* NVIC 配置 */
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_Init(&NVIC_InitStructure);

USART_Cmd(USART1, ENABLE);
}

/**
* @brief 获取标志位
* @param Nonw
* @retval None
*/
uint8_t Serial_GetRxFlag(void)
{
if (Serial_RxFlag == 1)
{
Serial_RxFlag = 0;
return 1;
}
return 0;
}

/**
* @brief 获取串口数据
* @param None
* @retval None
*/
uint8_t Serial_GetRxData(void)
{
return Serial_RxData;
}

/**
* @brief 串口1中断函数
* @param None
* @retval None
*/
void USART1_IRQHandler(void)
{
if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
{
Serial_RxData = USART_ReceiveData(USART1); // 获取数据
Serial_RxFlag = 1; // 标志位置1
USART_ClearITPendingBit(USART1, USART_IT_RXNE); // 清空终端挂起位
}
}

  1. 收发 HEX 数据包
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
/**
* @brief 发送数据包
* @param None
* @retval None
*/
void Serial_SendPacket(void)
{
Serial_SendByte(0xFF);
Serial_SendArray(Serial_TxPacket, 4);
Serial_SendByte(0xFE);
}

/**
* @brief 中断程序中接收数据包
* @param None
* @retval None
*/
void USART1_IRQHandler(void)
{
static uint8_t RxState = 0; // 当前状态
static uint8_t pRxPacket = 0; // 接收到第几个数据
if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
{
uint8_t RxData = USART_ReceiveData(USART1);

if (RxState == 0) // 状态0:包头
{
if (RxData == 0xFF)
{
RxState = 1; // 进入状态1
pRxPacket = 0; // 接收数据指针置零
}
}
else if (RxState == 1) // 状态1:数据
{
Serial_RxPacket[pRxPacket] = RxData; // 接收数据
pRxPacket ++; // 指针后移
if (pRxPacket >= 4)
{
RxState = 2; // 进入状态3
}
}
else if (RxState == 2) // 状态2:包尾
{
if (RxData == 0xFE)
{
RxState = 0; // 重新进入状态0
Serial_RxFlag = 1; // 置接收标志位为1
}
}

USART_ClearITPendingBit(USART1, USART_IT_RXNE);
}
}