自己写的delay函数,用定时器: 72Mhz
c
#include "stm32f10x.h"
#include "delay.h"
#include "led.h"
#include "key.h"
#include "buzzer.h"
#include "lightSensor.h"
#include "stdio.h"
#include "oled.h"
#include "counterSensor.h"
#include "encoder.h"
void app_systemClock_init(void){
// 开启 HSE
RCC_HSEConfig(RCC_HSE_ON);
// 等待HSE开启完
while(RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET);
// 配置锁相环 phase locked loop
RCC_PLLConfig(RCC_PLLSource_HSE_Div1,RCC_PLLMul_9);
// 开启锁相环
RCC_PLLCmd(ENABLE);
// 等待锁相环开启完
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
// 配置 AHB : advanced high-speed bus APB1: advance peripheral bus1
RCC_HCLKConfig(RCC_SYSCLK_Div1);
RCC_PCLK1Config(RCC_HCLK_Div2);
RCC_PCLK2Config(RCC_HCLK_Div1);
// 切换时钟来源,,, 切换来自于锁相环
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
// 等待时钟来源切换成功 ,, 0x00是 HSI ,,0x40是HSE ,, 0x80是锁相环 phase locked loop
while(RCC_GetSYSCLKSource() != 0x80);
// 开启指令预取,, instruction prefetch 72Mhz等待周期为2
FLASH_PrefetchBufferCmd(ENABLE);
FLASH_SetLatency(FLASH_Latency_2);
}
volatile uint32_t currentTick = 0;
void app_delay(uint32_t ms){
uint32_t expireTime = currentTick + ms;
while(currentTick < expireTime);
}
void app_tim3_timebaseInit(void){
// 开启tim3时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
TIM_TimeBaseInitTypeDef tim_timeBaseInitStructure;
tim_timeBaseInitStructure.TIM_Prescaler=71;
tim_timeBaseInitStructure.TIM_Period=999;
tim_timeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;
tim_timeBaseInitStructure.TIM_RepetitionCounter=0;
TIM_TimeBaseInit(TIM3,&tim_timeBaseInitStructure);
// 闭合时基单元的开关
TIM_Cmd(TIM3,ENABLE);
// 开启定时器update中断 ===> TIM允许发出中断请求,,但是cpu还不知道,要不要处理这个请求
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);
// nvic允许cpu响应这个中断,,没有nvic就不会跳转到中断函数
// 配置nvic : nested vectored intterupt controller
NVIC_InitTypeDef nvic_initStruct;
nvic_initStruct.NVIC_IRQChannel=TIM3_IRQn;
// 抢占优先级
nvic_initStruct.NVIC_IRQChannelPreemptionPriority = 0;
nvic_initStruct.NVIC_IRQChannelSubPriority=0;
nvic_initStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&nvic_initStruct);
}
// 中断响应函数
void TIM3_IRQHandler(void){
// 很多标志位都能触发中断
if(TIM_GetFlagStatus(TIM3,TIM_FLAG_Update) == SET){
currentTick++;
// 清除标志位
TIM_ClearFlag(TIM3,TIM_FLAG_Update);
}
}
void app_onBoardLED_init(void){
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
GPIO_InitTypeDef gpio_InitStruct;
gpio_InitStruct.GPIO_Pin = GPIO_Pin_13;
gpio_InitStruct.GPIO_Mode = GPIO_Mode_Out_OD;
gpio_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOC,&gpio_InitStruct);
GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_SET);
}
int main(void)
{
// 设置中断组
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
app_tim3_timebaseInit();
app_onBoardLED_init();
while(1)
{
GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_RESET);
app_delay(500);
GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_SET);
app_delay(500);
}
}
PWM : pulse width modulation 脉冲宽度调制


名词
- CNT : counter
- PSC : prescaler 预分频器
- ARR : auto reload register : 自动重装寄存器
- CCR : capture compare register : 捕获比较寄存器
- RCR : repetition counter register : 重复计数器
- PWM: pulse width modulation : 脉冲宽度调制

输出比较:
- 模式选择 : 8中不同的模式
ocxREf : output compare x reference : 输出比较通道x参考

这8种模式,,通过cnt 和 CCR 参数来产生结果的
相等有效: 当 cnt的值和 CCR的值相等的时候,,是有效的,,是高电压
toggle反转:当cnt和CCR值相等的时候,,电平发生一次反转
pwm1模式: 当cnt < CCR 这个 ocxREf 是高电压,否则是低电压
pwm2模式: 当cnt< CCR,输出低电压,否则是高电压
pwm :pulse width modulation
ccr : capture compare register

CH :channel 正常输出
CHxN : n:negative 互补输出
为什么要有互补输出 ,,,,


CHx 和 CHxN 是两个物理引脚,,你不可能为了用互补,,去换一个物理引脚,,加了个极性选择
DAC : digital to analog converter : 把数字量变成模拟电压
定时器主模式 master mode : 这个TIM可以向外发送同步信号
TRGO : trigger output 触发输出
普通情况下,,TIM自己玩自己的,,但是有时候,我们希望TIM触发 ADC,,或者ADC,或者触发别的TIM,,,
也就是外设之间的联动,,STM32搞了主从模式,,TIM可以对外发送同步信号
比如,,每1ms采样一次ADC,,,


三相无刷电机 : 四轴飞行器,电动车的后轮
c
// 告诉编译器,我有这个变量,,在别的文件定义了,至于在哪里,自己去找
extern uint16_t num;


