继电器(relay)是一种电控制器件,是当输入量(激励量)的变化达到规定要求时,在电气输出电路中使被控量发生预定的阶跃变化的一种电器。它具有控制系统(又称输入回路)和被控制系统(又称输出回路)之间的互动关系。通常应用于自动化的控制电 路中,它实际上是用小电流去控制大电流运作的一种“自动开关”。故在电路中起着自动调节、安全保护、转换电路等作用。
电磁式继电器一般由铁芯、线圈、衔铁、触点簧片等组成的。只要在线圈两端加上一定的电压,线圈中就会流过一定的电流,从而产生电磁效应,衔铁就会在电磁力吸引的作用下克服返回弹簧的拉力吸向铁芯,从而带动衔铁的动触点与静触点(常开触点)吸合。当线圈断电后,电磁的吸力也随之消失,衔铁就会在弹簧的反作用力返回原来的位置,使动触点与原来的静触点(常闭触点)释放。
这样吸合、释放,从而达到了在电路中的导通、切断的目的。对于继电器的“常开、常闭”触点,可以这样来区分:继电器线圈未通电时处于断开状态的静触点,称为“常开触点”;处于接通状态的静触点称为“常闭触点”。
继电器的控制原理很简单:
当控制端没电流流过或电流不够大时,继电器线圈就不吸合,常闭触点闭合,常开触点断开;当控制端有足够的电流流过时,继电器线圈就吸合,电磁感应使衔铁与永久磁铁产生吸引和排斥力矩,常闭触点断开,常开触点闭合。
1.晶体管驱动
当晶体管用来驱动继电器时,必须将晶体管的发射极接地。具体电路如下:
NPN 晶体管驱动时:当晶体管 T1基极被输入高电平时,晶体管饱和导通,集电极变为低电平,因此继电器线圈通电,触点 RL1吸合;当晶体管 T1 基级被输入低电平时,晶体管截止,继电器线圈断电,触电 RL1 断开。
PNP 晶体管驱动电路刚好和 NPN 驱动相反,即低电平时继电器导通,高电平时继电器断开。
电路中各元器件的作用:晶体管 T1可视为控制开关,一般选取 VCBO≈VCEO≥24V,放大倍数β一般选择在120~240之间,如 9013 、8050 等。电阻 R1 主要起限流作用,降低晶体管 T1 功耗,阻值为2 KΩ。电阻 R2使晶体管 T1可靠截止,阻值为5.1KΩ。二极管 D1 作用是关断时为线圈提供反向续流,一般选1N4148即可。
三极管驱动在插座、开关等电工产品中应用会比较多。
2.集成电路驱动
目前已使用多个驱动晶体管集成的集成电路,使用这种集成电路能简化驱动多个继电器的印制板的设计过程。驱动继电器的集成电路主要有TD62003AP、ULB2003等。
根据集成电路驱动器2003的输入输出特性,有人把它简称叫“驱动器”“反向器”“放大器”等。当2003输入端为高电平时,对应的输出口输出低电平,继电器线圈通电,继电器触点吸合;当2003输入端为低电平时,继电器线圈断电,继电器触点断开;在2003内部已集成起反向续流作用的二极管,因此可直接用它驱动继电器。
3.光耦隔离驱动
光耦亦称光电隔离器或光电耦合器,简称光耦。它是以光为媒介来传输电信号的器件,通常把发光器(红外线发光led)与受光器(光敏半导体管)封装在同一管壳内。当输入端加电信号时发光器发出光线,受光器接受光线之后就产生光电流,从输出端流出,从而实现了"电-光-电"转换。以光为媒介把输入端信号耦合到输出端的光电耦合器。
主要电路设计如下图:
该继电保护主要隔离应用的是EL817光耦芯片。该芯片无需供电,通过光耦二极管上拉5v电源输出即可正常工作,有效隔离了输出侧对主回路的电磁影响。
通过实验掌握STM32 芯片GPIO 的配置方法 掌握继电器模块的使用
硬件:PC 机一台;STM32开发板一套; 继电器模块一个
软件:Windows 10系统,Keil5集成开发环境
本文使用的1路继电器,如图6所示。LED1是信号输入指示灯,LED2是电源指示灯。P1接控制器,P3接单片机。当IN1输入为低电平,继电器的公共端常开,LED1指示灯亮起,当IN1输入为高电平时,继电器的公共端常闭,LED1指示灯熄灭。另外笔者这里的IN1接到单片的PC5。
本文将通过按键来控制继电器的状态,按键电路如下:
继电器的控制相对来说比较简单,和LED类似,只需设置高低电平即可控制继电器。本文通过KEY1来打开控制继电器的常开,KEY2来控制继电器的常闭开关。
关于按键的部分这里就不讲了,另外还用了串口和滴答定时器,看笔者以前的文章吧。
Systick系统定时器
按键
串口通信
继电器的部分很简单。
1.初始化GPIO
/**
* @brief 继电器IO引脚初始化
* @param None
* @retval None
*/
void RELAY_GPIO_Init(void)
{
/* 定义IO硬件初始化结构体变量 */
GPIO_InitTypeDef GPIO_InitStructure;
/* 使能(开启)继电器引脚对应IO端口时钟 */
RELAY_RCC_CLOCKCMD(RELAY_RCC_CLOCKGPIO, ENABLE);
/* 设定继电器对应引脚IO编号 */
GPIO_InitStructure.GPIO_Pin = RELAY_GPIO_PIN;
/* 设定继电器对应引脚IO最大操作速度 :GPIO_Speed_50MHz */
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
/* 设定继电器对应引脚IO为输出模式 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
/* 初始化继电器对应引脚IO */
GPIO_Init(RELAY_GPIO, &GPIO_InitStructure);
/* 设置引脚输出为低电平,此时继电器(公共端——常闭) */
RELAY_ON;
}
笔者这里使用的是PC5,当然你也可以自行更换引脚。
2.控制继电器
控制继电器是通过宏定义的方式实现的。
#if 0 /* 调用标准库函数方法 */
#define RELAY_ON GPIO_ResetBits(RELAY_GPIO,RELAY_GPIO_PIN) //输出低电平,继电器(公共端——常开)
#define RELAY_OFF GPIO_SetBits(RELAY_GPIO,RELAY_GPIO_PIN) //输出高电平,继电器(公共端——常闭)
#define RELAY_TOGGLE {
RELAY_GPIO->ODR ^=RELAY_GPIO_PIN;} //输出反转,继电器状态改变
#else /* 直接操作寄存器方法 */
#define RELAY_ON {
RELAY_GPIO->BRR=RELAY_GPIO_PIN;} //输出低电平,继电器(公共端——常开)
#define RELAY_OFF {
RELAY_GPIO->BSRR=RELAY_GPIO_PIN;} //输出高电平,继电器(公共端——常闭)
#define RELAY_TOGGLE {
RELAY_GPIO->ODR ^=RELAY_GPIO_PIN;} //输出反转,继电器状态改变
#endif
当然也可可以封装成库函数。函数如下:
/**
* @brief 设置板载继电器的状态
* @param tate:设置继电器的状态。
* 可选值:RELAYState_OFF:继电器(公共端——常闭)
* 可选值:RELAYState_ON: 继电器(公共端——常开)
* @retval None
*/
void RELAY_SetState(RELAYState_TypeDef state)
{
/* 检查输入参数是否合法 */
assert_param(RELAYState_TypeDef(state));
/* 判断设置的继电器状态,如果设置为继电器常开 */
if(state==RELAYState_ON)
{
RELAY_ON;
}
else /* state=RELAYState_OFF:设置继电器(公共端——常开) */
{
RELAY_OFF;
}
}
3.继电器的状态检测
设置了继电器的开闭,接下来通过检测GPIO的状态来检测继电器的开闭状态。
/**
* @brief 读取继电器的状态
* @param RELAYState_OFF:继电器(公共端——常闭)
* RELAYState_ON: 继电器(公共端——常开)
* @retval None
*/
uint8_t RELAY_GetState(void)
{
uint8_t relay_state=RELAYState_ON;
if((RELAY_GPIO->ODR & RELAY_GPIO_PIN)!= (uint32_t)Bit_RESET)
relay_state=RELAYState_OFF;
return relay_state;
}
好了,接下来看看主函数是如何调用的。
/**
* @brief mian
* @param None
* @retval int
*/
int main(void)
{
//滴答定时器初始化
SysTick_Init();
/* USART1 配置模式为 115200 8-N-1,中断接收 */
USART1_Config();
/* 初始继电器IO */
RELAY_GPIO_Init();
/* 初始化按键 */
KEY_GPIO_Init();
printf("继电器\r\n");
/* 无限循环 */
while (1)
{
if(KEY1_StateRead()==KEY_DOWN)
{
RELAY_ON; //输出低电平,继电器(公共端——常开)
printf("当前继电器状态为:常闭 \r\n");
}
if(KEY2_StateRead()==KEY_DOWN)
{
RELAY_OFF;//输出高电平,继电器(公共端——常闭)
printf("当前继电器状态为:常开 \r\n");
}
if(RELAY_GetState()==RELAYState_OFF)
{
Delay_ms(20);
printf("当前继电器状态为:常闭 \r\n");
}
else
{
printf("当前继电器状态为:常开 \r\n");
Delay_ms(20);
}
Delay_ms(200);
}
}
先进行一系列的初始化,然后就通过按键来控制继电器的状态,不断检测继电器状态,并点打印输出继电器的状态信息。
我们在串口的例子的基础上进行配置。
串口通信(HAL库)
这里用到了PA0、PC13和PC5,将PC5配置成输出,KEY1的引脚是PA0,KEY2的引脚是C13,我们将PA0 和PC13的GPIO设置为输入模式。
生成工程即可。
关于按键的实现可参考笔者以前的博客:
按键
HAL库的实现和标准库一样,只是函数不同罢了。
这里只贴出主函数的代码。完整工程请通过后文提示获取。
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
HAL_UART_Receive_IT(&huart1, (uint8_t *)&RxBuffer, 1);
/* USER CODE END 2 */
printf("继电器\r\n");
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
if(KEY1_StateRead()==KEY_DOWN)
{
RELAY_ON; //输出低电平,继电器(公共端——常开)
printf("当前继电器状态为:常闭 \r\n");
}
if(KEY2_StateRead()==KEY_DOWN)
{
RELAY_OFF;//输出高电平,继电器(公共端——常闭)
printf("当前继电器状态为:常开 \r\n");
}
if(RELAY_GetState()==RELAYState_OFF)
{
HAL_Delay(20);
printf("当前继电器状态为:常闭 \r\n");
}
else
{
printf("当前继电器状态为:常开 \r\n");
HAL_Delay(20);
}
HAL_Delay(200);
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
不管是使用何种库,结果都是一样的,每个200ms输出继电器状态,使用按键控制控制继电器状态,串口就会打印继电器的状态信息。
欢迎访问我的网站:
BruceOu的哔哩哔哩
BruceOu的主页
BruceOu的博客
BruceOu的CSDN博客
BruceOu的简书
接收更多精彩文章及资源推送,请订阅我的微信公众号: