1.STM32F103的系统时钟最高频率是72MHZ
2.STM32F103的定时器TIM 的CNT计数值最大为65535
3.STM32F103的定时器TIM 的预分频 系数 PSC 的数值 = 72M / 定时器计数频率
因为CNT最大值为65535 所以, 这里有个问题, 当定时器计数频率太高的时候, 例如72M的计数频率.
1秒钟最多有72000000个计数, 当计数到65535个的时候是 0.0009102083秒 也就是 1098.65HZ
要想计数到1秒, 必须修改PSC,提高分频系数. 降低定时器计数频率
经过实际测量, STM32F103C8T6 最高输出方波的频率为18mhz. 再往上就无法输出了.
(有可能是我这个示波器的问题, 我的是pc虚拟示波器最大才20m的采样频率. )
后来实验确定最高确实只能达到18mhz, 因为ARR为1, PSC为0 已经是最高了. 不可能再高了.
估计STM32F4系列应该会更高一些吧.
下面列出了表格.
系统时钟频率 | PSC | 定时器计数频率 最高输出方波频率 | 定时器计数频率(MHZ) | 最低输出方波频率 |
72000000 | 0 | 72000000.00 | 72.00 | 1098.65 |
72000000 | 1 | 36000000.00 | 36.00 | 549.32 |
72000000 | 3 | 18000000.00 | 18.00 | 274.66 |
72000000 | 5 | 12000000.00 | 12.00 | 183.11 |
72000000 | 7 | 9000000.00 | 9.00 | 137.33 |
72000000 | 11 | 6000000.00 | 6.00 | 91.55 |
72000000 | 23 | 3000000.00 | 3.00 | 45.78 |
72000000 | 35 | 2000000.00 | 2.00 | 30.52 |
72000000 | 71 | 1000000.00 | 1.00 | 15.26 |
72000000 | 719 | 100000.00 | 0.10 | 1.53 |
void ChangCLK(uint32_t fclk )
{
float rfclk = fclk * 2 ; //pwm波的频率是一高一低,两个才是一个周期,所以必须是两倍才能正常输出.同样频率的方波.
//重复计算,MaxCOUNT 和 TIME4_PSC 直到满足条件
while(1)
{
//TIME4_PSC + 1// 预分配需要72 但是要填71. 因为STM32器件就是这么规定的.
//计数频率 = 时钟主频 / 预分频系数
JiShuPinLv = TIME_ZhuPinLv / (TIME4_PSC + 1.0);
//目标频率 = 计数频率 * 计数个数MaxCOUNT;
//目标周期 = 1/目标频率;
//计数周期 = 1/计数频率;
//计数个数MaxCOUNT = 目标周期 / 计数周期
//得
//计数个数MaxCOUNT = (1/目标频率) / (1/计数频率)
//MaxCOUNT = (1.0 / rfclk) / (1 / JiShuPinLv);
//这种做法, 不适合程序执行, 耗时又不准,简化推导过程如下
//x = (1/a) / (1/b)
//x * a = a * (1/a) / (1/b)
//x * a = 1 / (1/b)
//x * a = b
//x = b/a
//代入简化后
MaxCOUNT = JiShuPinLv / rfclk;
if(TIME4_PSC == 0 || TIME4_PSC >= 65535)
{
break; //到极限了,下面就不要再计算PSC了
}
if(MaxCOUNT <= 2)
{
//计数周期大于目标周期, 那么减少预分频数值,提高计数频率
TIME4_PSC = TIME4_PSC / 10;
if(TIME4_PSC > 0)
{
continue; //下一循环再调整 ,并同时重新计算MaxCOUNT
}
}
else if( MaxCOUNT>=65535)
{
//计数值的范围不够了.那么增加预分频数值,降低计数频率
TIME4_PSC = TIME4_PSC * 10;
if(TIME4_PSC < 65535)
{
continue; //下一循环再调整 ,并同时重新计算MaxCOUNT
}
}else{
//一般情况下都是直接退出.
break;
}
}
if(MaxCOUNT <= 2) {
MaxCOUNT =2;//ARR不能等于0 否则就没有频率输出了.
}else if(TIME4_PSC > 65536) {
MaxCOUNT = 65536;
}
TIME4->PSC = TIME4_PSC;
TIME4->ARR = MaxCOUNT - 1; //-1是 STM32 器件本身的特点,填入MaxINT-1才是真正的按照MaxINT运行. //Period == ARR
//TIME4->CNT = 0;
//TIME4->CCR1 = 0 ; //输出比较模式下这个寄存器控制初相位应该都为0, pwm模式才是控制的高电平周期
}