继电器是我们生活中常用的一种控制设备,通俗的意义上来说就是开关,在条件满足的情况下关闭或者开启。继电器的开关特性在很多控制系统尤其是离散的控制系统中得到广泛的应用。从另一个角度来说,由于为某一个用途设计使用的电子电路,最终或多或少都需要和一些机械设备相交互所以继电器也起到电子设备和机械设备的接口作用。
继电器驱动原理图

线圈不分正负极
D1是肖特基二极管(正向导通,反向截止)
三极管截止时,D1才慢慢消除线圈里存留的电,D1起到保护三极管作用
R1是限流电阻
三极管NPN型,PF0输出高电平,继电器工作
如果三极管是PNP型,单片机引脚输出低电平,继电器就工作了
继电器接线方式:

今日任务:复习TIM1,学习通用定时器
TIM2、TIM3、TIM4、TIM5配置方式都是相同的
开始编写代码!
1. //宏定义,方便后期代码移植
2. #define RELAY_PORT GPIOF
3. #define RELAY GPIO_Pin_0
编写继电器控制函数
把重装载值和预分频值拿出来做形参,方便修改,取值范围都是0~65535
具体配置过程参考代码的注释
1. // 0-65535
2. void RELAY_Config(uint16_t Period, uint16_t Prescaler)
3. {
4. //先开时钟
5. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF, ENABLE);
6. RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //TIM2在APB1总线
7.
8. GPIO_InitTypeDef GPIO_InitStructure;
9. TIM_TimeBaseInitTypeDef TIM_InitStructure;
10. NVIC_InitTypeDef NVIC_InitStructure;
11.
12. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //配置推挽输出
13. GPIO_InitStructure.GPIO_Pin = RELAY;
14. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
15. GPIO_Init(RELAY_PORT, &GPIO_InitStructure);
16.
17. //继电器输入一个高电平信号是工作状态,所以先初始化低电平
18. GPIO_ResetBits (RELAY_PORT, RELAY); //LOW
19.
20. TIM_InitStructure.TIM_Period = Period; //重装载值
21. TIM_InitStructure.TIM_Prescaler = Prescaler; //预分频值
22. TIM_InitStructure.TIM_ClockDivision = TIM_CKD_DIV1; //时钟分割无
23. TIM_InitStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数
24. TIM_InitStructure.TIM_RepetitionCounter = DISABLE; //先禁用 重复计数次数
25. TIM_TimeBaseInit(TIM2, &TIM_InitStructure); //初始化
26.
27. //开中断之前,先清空中断!!!
28. TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
29.
30. //开启中断,要或 | 上触发中断源TIM_IT_Trigger
31. TIM_ITConfig(TIM2, TIM_IT_Update | TIM_IT_Trigger, ENABLE);
32. TIM_Cmd(TIM2, ENABLE);
33.
34. //中断优先级分组,先随意,因为没有多个中断同时触发
35. NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
36. NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; //中断源
37. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
38. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//抢占
39. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;//响应
40. NVIC_Init(&NVIC_InitStructure);
41.
42. }
定时器2的中断服务函数
1. void TIM2_IRQHandler(void)
2. {
3. if (TIM_GetITStatus (TIM2, TIM_IT_Update) == SET) //判断TIM_GetITStatus == 1 判断是否进入中断
4. {
5. //写位操作 //SET - GPIO_ReadOutputDataBit 1-读取到的输出状态位,就是取非操作
6. GPIO_WriteBit (RELAY_PORT, RELAY, (BitAction)(SET - GPIO_ReadOutputDataBit(RELAY_PORT, RELAY) ) );
7. TIM_ClearITPendingBit(TIM2, TIM_IT_Update); //清空中断
8. }
9. }
main函数
1. int main(void)
2. {
3. RELAY_Config (2000-1, 7200-1);//人工减1,系统加1
4.
5. //每次中断都翻转电平,200ms翻转一次,周期就是400ms
6. while(1)
7. {
8. }
9. }
RELAY_Config(2000-1, 7200-1);函数形参讲解:
没有进行时钟分割,就是72MHz,1S计72M个数
现在进行7200分频,相当于1s计数72M/7200 = 10000,就是一秒要计一万个数
计数一次就是 1/10000 = 0.0001 = 100us
如果定时200ms,重装载值 = 0.2s*10000 = 2000,计数2000 = 0.2s = 200ms
最后用逻辑分析仪抓取一下波形,观察实验现象,200ms高电平,200ms低电平,占空比50%
没得问题!!!

这个波形,不是PWM,是手动设置的一个周期的波形频率……