赞
踩
最近用到F4的地方比较多,网上代码还是F1多一些,便需要移植代码,如何快速移植代码呢?
看下面这篇文章
首先就是STM32的外设了。
STM32F407ZGT6 作为 MCU,该芯片是
STM32F407 里面配置非常强大的了,它拥有的资源包括:集成 FPU 和 DSP 指令,并具有 192KB
SRAM、1024KB FLASH、12 个 16 位定时器、2 个 32 位定时器、2 个 DMA 控制器(共 16 个通道)、3 个 SPI、2 个全双工 I2S、3 个 IIC、6 个串口、2 个 USB(支持 HOST /SLAVE)、2 个CAN、3 个 12 位 ADC、2 个 12 位 DAC、1 个 RTC(带日历功能)、1 个 SDIO 接口、1 个 FSMC接口、1 个 10/100M 以太网 MAC 控制器、1 个摄像头接口、1 个硬件随机数生成器、以及 112个通用 IO 口等。该芯片的配置十分强悍,很多功能相对 STM32F1 来说进行了重大改进,比如
FSMC 的速度,F4 刷屏速度可达 3300W 像素/秒,而 F1 的速度则只有 500W 左右。
STM32F103ZETT6 作为 MCU,该芯片是
STM32F103 里面配置非常强大的了,它拥有的资源包括:64KB SRAM、512KB FLASH、2 个基本定时器、4 个通用定时器、2 个高级定时器、2 个 DMA 控制器(共 12 个通道)、3 个 SPI、2 个 IIC、5 个串口、1 个 USB、1 个 CAN、3 个 12 位 ADC、1 个 12 位 DAC、1 个 SDIO 接口、1 个 FSMC 接口以及 112 个通用 IO 口。该芯片的配置十分强悍,并且还带外部总线(FSMC)
可以用来外扩 SRAM 和连接 LCD 等,通过 FSMC 驱动 LCD,可以显著提高 LCD 的刷屏速度,是 STM32F1 家族常用型号里面,最高配置的芯片了
然后是比较重要的一个功能。
为什么说时钟重要呢,在做SPI或者一些对时的时候,这个时候时钟的重要性就突显出来了。
SYSCLK(系统时钟) =168MHz
AHB 总线时钟(HCLK=SYSCLK) =168MHz
APB1 总线时钟(PCLK1=SYSCLK/4) =42MHz
APB2 总线时钟(PCLK2=SYSCLK/2) =84MHz
PLL 主时钟 =168MHz
SYSCLK(系统时钟) =72MHz
AHB 总线时钟(使用 SYSCLK) =72MHz
APB1 总线时钟(PCLK1=SYSCLK/2) =36MHz
APB2 总线时钟(PCLK2) =72MHz
PLL 时钟 =72MHz
1、输入浮空
2、输入上拉
3、输入下拉
4、模拟输入
5、开漏输出
6、推挽输出
7、推挽式复用功能
8、开漏式复用功能
模式就不用说了,这个大家应该都知道,重要的是如何配置。
一定要注意使能IO口时钟,而且要写对 博主就踩了几次坑
使能 IO 口时钟。调用函数为 RCC_AHB1PeriphClockCmd ()
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);//使能GPIOF时钟
初始化 IO 参数。调用函数 GPIO_Init();
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
GPIO_Init(GPIOF, &GPIO_InitStructure);//初始化GPIO
上面的是输出配置,下面看一下输入配置,大家可以比较一下。
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;//普通输入模式
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100M
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化GPIOE2,3,4
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //设置成上拉输入
GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化GPIOE4,3
然后我们看一下不同点
首先F4的io的时钟挂载在AHB1下,调用 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);//使能GPIOF时钟 其次 typedef struct { uint32_t GPIO_Pin; GPIOMode_TypeDef GPIO_Mode; GPIOSpeed_TypeDef GPIO_Speed; GPIOOType_TypeDef GPIO_OType;//配置输出模式 GPIOPuPd_TypeDef GPIO_PuPd; //上下拉的配置 }GPIO_InitTypeDef; typedef enum { GPIO_PuPd_NOPULL = 0x00, GPIO_PuPd_UP = 0x01, GPIO_PuPd_DOWN = 0x02 }GPIOPuPd_TypeDef; f4能在GPIO_Init配置时就配置引脚的上下拉高低电平 typedef enum { GPIO_OType_PP = 0x00, GPIO_OType_OD = 0x01 }GPIOOType_TypeDef; f4配置了输出后专门可以选择配置开漏输出和推挽输出,也就是比103分的更细一些了 f4的速度最高可以配置为100mhz 103只有50mhz
首先两者都要在main函数里面设置中断优先级的分组,且只设置一次设置了就别改了避免发生错误
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
STM32F40xx/STM32F41xx 的 92 个中断里面,包括 10 个内核中断和 82 个可屏蔽中断,具
有 16 级可编程的中断优先级,而我们常用的就是这 82 个可屏蔽中断
说了 CM3 内核支持 256 个中断,这里用 8 个 32 位寄存器来控制,每个位控制一个中断。但是
STM32F103 的可屏蔽中断只有 60 个
他们NVIC的配置是一样的
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//串口 1 中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1 ;// 抢占优先级为 1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;// 子优先级位 2
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ 通道使能
NVIC_Init(&NVIC_InitStructure); //根据上面指定的参数初始化 NVIC 寄存器
他们之间的中断服务函数都是一样的
EXTI0_IRQHandler
EXTI1_IRQHandler
EXTI2_IRQHandler
EXTI3_IRQHandler
EXTI4_IRQHandler
EXTI9_5_IRQHandler
EXTI15_10_IRQHandler
STM32F407 的中断控制器支持 22
个外部中断/事件请求。每个中断设有状态位,每个中断/事件都有独立的触发和屏蔽设置。
STM32F407 的 22 个外部中断为:
EXTI 线 0~15:对应外部 IO 口的输入中断。
EXTI 线 16:连接到 PVD 输出。
EXTI 线 17:连接到 RTC 闹钟事件。
EXTI 线 18:连接到 USB OTG FS 唤醒事件。
EXTI 线 19:连接到以太网唤醒事件。
EXTI 线 20:连接到 USB OTG HS(在 FS 中配置)唤醒事件。
EXTI 线 21:连接到 RTC 入侵和时间戳事件。
EXTI 线 22:连接到 RTC 唤醒事件。
STM32F4 供 IO 口使用的中断线只有 16 个
配置步骤
使能SYSCFG时钟:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
初始化IO口为输入。
GPIO_Init();
设置IO口与中断线的映射关系。
void SYSCFG_EXTILineConfig();
初始化线上中断,设置触发条件等。
EXTI_Init();
配置中断分组(NVIC),并使能中断。
NVIC_Init();
编写中断服务函数。
EXTIx_IRQHandler();
清除中断标志位
EXTI_ClearITPendingBit();
实例
一定要注意这里
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);//使能SYSCFG时钟
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource3);//PE3 连接到中断线3
这两个是不一样的,F4是使能SYSCFG时钟来配置中断
NVIC_InitTypeDef NVIC_InitStructure; EXTI_InitTypeDef EXTI_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);//使能SYSCFG时钟 SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource3);//PE3 连接到中断线3 EXTI_InitStructure.EXTI_Line =EXTI_Line3 EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//中断事件 EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿触发 EXTI_InitStructure.EXTI_LineCmd = ENABLE;//中断线使能 EXTI_Init(&EXTI_InitStructure);//配置 NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn;//外部中断3 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;//抢占优先级2 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;//子优先级2 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能外部中断通道 NVIC_Init(&NVIC_InitStructure);//配置
中断服务格式
void EXTI3_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line3)!=RESET)//判断某个线上的中断是否发生
{ …中断逻辑…
EXTI_ClearITPendingBit(EXTI_Line3); //清除 LINE 上的中断标志位
}
}
初始化IO口为输入。
GPIO_Init();
开启IO口复用时钟。
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
设置IO口与中断线的映射关系。
void GPIO_EXTILineConfig();
初始化线上中断,设置触发条件等。
EXTI_Init();
配置中断分组(NVIC),并使能中断。
NVIC_Init();
编写中断服务函数。
EXTIx_IRQHandler();
清除中断标志位
EXTI_ClearITPendingBit();
实例
io初始化省略 EXTI_InitTypeDef EXTI_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; //使能复用功能时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //配置 GPIO 与中断线的映射关系 //void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource) GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource3); 将中断线 3 与 GPIOE 映射起来,那么很显然是 GPIOE.3 与 EXTI3 中断线连接了 //初始化线上中断,设置触发条件等 EXTI_InitStructure.EXTI_Line=EXTI_Line3; //设置中断线的标号 EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //中断模式 //有两个模式中断和事件可选这里是中断 EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//设置触发方式 //设置触发方式,有上升沿和下降沿,还有双边沿,这里配置的是下降沿 EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器 //配置中断分组(NVIC),并使能中断 NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn; //使能外部中断通道 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级2 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01; //子优先级1 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道 NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器 后面就是根据具体的要求写中断函数了
中断服务格式
void EXTI3_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line3)!=RESET)//判断某个线上的中断是否发生
{
中断逻辑…
EXTI_ClearITPendingBit(EXTI_Line3); //清除 LINE 上的中断标志位
}
}
串口也是很重要的一个环节。
配置步骤
串口时钟使能:RCC_APBxPeriphClockCmd(); GPIO时钟使能:RCC_AHB1PeriphClockCmd(); 引脚复用映射: GPIO_PinAFConfig(); GPIO端口模式设置:GPIO_Init(); 模式设置为GPIO_Mode_AF 串口参数初始化:USART_Init(); 开启中断并且初始化NVIC(如果需要开启中断才需要这个步骤) NVIC_Init(); USART_ITConfig(); 使能串口:USART_Cmd(); 编写中断处理函数:USARTx_IRQHandler(); 串口数据收发: void USART_SendData();//发送数据到串口,DR uint16_t USART_ReceiveData();//接受数据,从DR读取接受到的数据 串口传输状态获取: FlagStatus USART_GetFlagStatus(); void USART_ClearITPendingBit();
实例
//GPIO端口设置 GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //使能GPIOA时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//使能USART1时钟 //串口1对应引脚复用映射 GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1); //GPIOA9复用为USART1 GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1); //GPIOA10复用为USART1 //USART1端口配置 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; //GPIOA9与GPIOA10 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度50MHz GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉 GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA9,PA10 //USART1 初始化设置 USART_InitStructure.USART_BaudRate = bound;//波特率设置 USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式 USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位 USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制 USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式 USART_Init(USART1, &USART_InitStructure); //初始化串口1 USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启相关中断 //Usart1 NVIC 配置 NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//串口1中断通道 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;//抢占优先级3 NVIC_InitStructure.NVIC_IRQChannelSubPriority =3; //子优先级3 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能 NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器、 USART_Cmd(USART1, ENABLE); //使能串口1 中断服务函数
串口时钟使能,GPIO时钟使能:RCC_APB2PeriphClockCmd();
串口复位:USART_DeInit(); 这一步不是必须的
GPIO端口模式设置:GPIO_Init();
串口参数初始化:USART_Init();
开启中断并且初始化NVIC(如果需要开启中断才需要这个步骤)
NVIC_Init();
USART_ITConfig();
使能串口:USART_Cmd();
编写中断处理函数:USARTx_IRQHandler();
串口数据收发:
void USART_SendData();//发送数据到串口,DR
uint16_t USART_ReceiveData();//接受数据,从DR读取接受到的数据
串口传输状态获取:
FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG);
void USART_ClearITPendingBit(USART_TypeDef* USARTx, uint16_t USART_IT);
实例
GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; //①串口时钟使能,GPIO 时钟使能,复用时钟使能 RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1| RCC_APB2Periph_GPIOA, ENABLE); //使能 USART1,GPIOA 时钟 //②串口复位 USART_DeInit(USART1); //复位串口 1 //③GPIO 端口模式设置 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //ISART1_TX PA.9 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出 GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化 GPIOA.9 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //USART1_RX PA.10 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入 GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化 GPIOA.10 //④串口参数初始化 USART_InitStructure.USART_BaudRate = 115200; //波特率设置 USART_InitStructure.USART_WordLength = USART_WordLength_8b; //字长为 8 位 USART_InitStructure.USART_StopBits = USART_StopBits_1; //一个停止位 USART_InitStructure.USART_Parity = USART_Parity_No; //无奇偶校验位 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无硬件数据流控制 USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//收发模式 USART_Init(USART1, &USART_InitStructure); //⑤初始化 NVIC NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ; //抢占优先级 3 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级 3 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ 通道使能 NVIC_Init(&NVIC_InitStructure); //中断优先级初始化 //⑤开启中断 USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //开启中断 //⑥使能串口 USART_Cmd(USART1, ENABLE); //使能串口 中断服务函数
1.首先都要开启usart的时钟和对应串口引脚的时钟,不同的是103串口的tx引脚配置的复用推挽输出,而rx配置的是浮空输入,而407rx,tx两个都配置的复用推完输出
2.407需要对串口对应的引脚设置引脚复用器映射:调用 GPIO_PinAFConfig 函数。
这两点大家一定要注意!
103的定时器资源
103的高级定时器是TIM1和TIM8
2,3,4,5是通用定时器
6,7是基本定时器
都是16位的
407的定时器资源
407的高级定时器是TIM1和TIM8
2,3,4,5,9,10,11,12,13,14是通用定时器
6,7是基本定时器
有16位和32位的
这个基本定时器的配置是一样的
能定时器时钟。
RCC_APB1PeriphClockCmd();
初始化定时器,配置ARR,PSC。
TIM_TimeBaseInit();
开启定时器中断,配置NVIC。
void TIM_ITConfig();
NVIC_Init();
使能定时器。
TIM_Cmd();
编写中断服务函数。
TIMx_IRQHandler();
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能 //定时器TIM3初始化 TIM_TimeBaseStructure.TIM_Period = arr; //设置自动重装载的值 TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式 TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位 TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断 //中断优先级NVIC设置 NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3中断 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级0级 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //从优先级3级 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能 NVIC_Init(&NVIC_InitStructure); //初始化NVIC寄存器 TIM_Cmd(TIM3, ENABLE); //使能TIMx //定时器3中断服务函数 void TIM3_IRQHandler(void) { if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET) //溢出中断 { LED1=!LED1;//DS1翻转 } TIM_ClearITPendingBit(TIM3,TIM_IT_Update); //清除中断标志位 }
使能定时器14和相关IO口时钟。 使能定时器14时钟:RCC_APB1PeriphClockCmd(); 使能GPIOF时钟:RCC_AHB1PeriphClockCmd (); 初始化IO口为复用功能输出。函数:GPIO_Init(); GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //复用功能GPIOF9复用映射到定时器14 GPIO_PinAFConfig(GPIOF,GPIO_PinSource9,GPIO_AF_TIM14); 初始化定时器:ARR,PSC等: TIM_TimeBaseInit(); 初始化输出比较参数: TIM_OC1Init(); 使能预装载寄存器: TIM_OC1PreloadConfig(TIM14, TIM_OCPreload_Enable); 使能自动重装载的预装载寄存器允许位 TIM_ARRPreloadConfig(TIM14,ENABLE); 使能定时器。 TIM_Cmd(); 不断改变比较值CCRx,达到不同的占空比效果: TIM_SetCompare1();
GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14,ENABLE); //TIM14时钟使能 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE); //使能PORTF时钟 GPIO_PinAFConfig(GPIOF,GPIO_PinSource9,GPIO_AF_TIM14); //GPIOF9复用为定时器14 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //GPIOF9 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //复用功能 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //速度100MHz GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉 GPIO_Init(GPIOF,&GPIO_InitStructure); //初始化PF9 TIM_TimeBaseStructure.TIM_Prescaler=psc; //定时器分频 TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式 TIM_TimeBaseStructure.TIM_Period=arr; //自动重装载值 TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; TIM_TimeBaseInit(TIM14,&TIM_TimeBaseStructure);//初始化定时器14 //初始化TIM14 Channel1 PWM模式 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式2 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //输出极性:TIM输出比较极性低 TIM_OC1Init(TIM14, &TIM_OCInitStructure); //根据T指定的参数初始化外设TIM1 4OC1 TIM_OC1PreloadConfig(TIM14, TIM_OCPreload_Enable); //使能TIM14在CCR1上的预装载寄存器 TIM_ARRPreloadConfig(TIM14,ENABLE);//ARPE使能 TIM_Cmd(TIM14, ENABLE); //使能TIM14
使能定时器3和相关IO口时钟。 使能定时器3时钟: RCC_APB1PeriphClockCmd(); 使能GPIOB时钟: RCC_APB2PeriphClockCmd(); 初始化IO口为复用功能输出。函数: GPIO_Init(); GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; 这里我们是要把PB5用作定时器的PWM输出引脚,所以要重映射配置, 所以需要开启AFIO时钟。同时设置重映射。 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); 初始化定时器:ARR,PSC等: TIM_TimeBaseInit(); 初始化输出比较参数: TIM_OC2Init(); 使能预装载寄存器: TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable); 使能定时器。 TIM_Cmd(); 不断改变比较值CCRx,达到不同的占空比效果: TIM_SetCompare2();
GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //使能定时器3时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE); //使能GPIO外设和AFIO复用功能模块时钟 GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); //Timer3部分重映射 TIM3_CH2->PB5 //设置该引脚为复用输出功能,输出TIM3 CH2的PWM脉冲波形 GPIOB.5 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //TIM_CH2 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIO //初始化TIM3 TIM_TimeBaseStructure.TIM_Period = arr; //设置自动重装载值 TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式 TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位 //初始化TIM3 Channel2 PWM模式 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高 TIM_OC2Init(TIM3, &TIM_OCInitStructure); //根据T指定的参数初始化外设TIM3 OC2 TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable); //使能TIM3在CCR2上的预装载寄存器 TIM_Cmd(TIM3, ENABLE); //使能TIM3
如果移植之后发现不能用,首先检查IO的使能,如果使能没有问题进一步检查引脚配置的模式。该复用成对应功能的有没有复用。有用中断要注意F4中断时钟初始化的写法,如果用到SPI这种需要时序的,确认上面的没问题了,在检查一下时钟。
如果你的SPI发现自己动一动线就有数据了,这个时候就去看引脚的模式,是不是推挽输出。该浮空输入的有没有浮空输入,那个默认无上下拉的配置直接不要,不要写那个东西。
跳转链接
我这篇文章也是引用这位博主的文章,在此感谢。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。