一、项目介绍
本项目主要适用学生日常在宿舍睡觉前,需下床手动关闭宿舍灯等场景,通过手机蓝牙控制宿舍灯的开闭,从而达到睡前不用下床即可关闭灯的效果。
项目主要模块部分:51单片机,sg90舵机,蓝牙模块。
二、sg90舵机
1.PWM
PWM,英文名Pulse Width Modulation,是脉冲宽度调制缩写,它是通过对一系列脉冲的宽度进行调制,等效出所需要的波形(包含形状以及幅值),对模拟信号电平进行数字编码,也就是说通过调节占空比的变化来调节信号、能量等的变化,占空比就是指在一个周期内,信号处于高电平的时间占据整个信号周期的百分比,例如方波的占空比就是50%
脉冲宽度调制
通过占空比编码模拟信号
占空比:一个周期内,高电平占据时长的百分比
2.用PWM实现信号输出
通过IO口软件模拟信号输出,相对硬件PWM来说精准度略差。
3.控制SG90舵机
3.1初识sg90舵机
![](https://img-blog.csdnimg.cn/img_convert/68c64ca4456311b86bcf611d9dbed5f6.jpeg)
舵机有常用三根接线,黄色为PWM信号控制线,红色为VCC,棕色为GND,主要用来实现转动。
3.2.控制舵机
往黄色信号线输入PWM信号,PWM波的频率不能太高,大约50HZ,20ms左右。
转动角度参考数据:
0.5ms-------------0度;2.5%对应函数中占空比为250
1.0ms------------45度;5.0%对应函数中占空比为500
1.5ms------------90度;7.5%对应函数中占空比为750
2.0ms-----------135度;10.0%对应函数中占空比为1000
2.5ms-----------180度;12.5%对应函数中占空比为1250
三、代码实现
#include <reg52.h>
#include<intrins.h>
#include <string.h>
#define SIZE 12
sfr AUXR=0x8E;
sbit sg90_con=P1^1;
sbit led1=P3^7;
char cmd[12];
int cnt=0;
int jd;
void Delay300ms() //@11.0592MHz
{
unsigned char i, j, k;
_nop_();
i = 3;
j = 26;
k = 223;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void Time0_init()
{
TMOD=0x01;//设置定时器工作模式
TL0=0x33;//设置500us低八位
TH0=0xFE;//设置500us高八位
TR0=1;//打开定时器0
TF0=0;//设置定时器没溢出
EA=1;//打开总中断
ET0=1;//打开定时器0中断
}
void UartInit(void) //9600bps@11.0592MHz
{
AUXR=0x01;
SCON=0x50;//8位数据,可变波特率 REN置1
TMOD &= 0x0F;//定时器时钟为12T
TMOD |= 0x20;//串口1选择定时器1为波特率发生器
TH1=0xFD;//设定定时初值
TL1=0xFD;//波特率为9600
TR1=1;//启动定时器1
EA=1;//开启总中断
ES=1;//开启串口中断
}
void sendByte(char data_msg)
{
SBUF=data_msg;
while(!TI);//TI为发送中断请求位
TI=0;
}
void sendString(char *str)
{
while(*str!='\0'){
sendByte(*str);
str++;
}
}
void main()
{
Delay300ms();//上电后延时稳定一下
jd=1;//舵机初始角度
sg90_con=1;//给舵机一个高电平
while(1){
sendString("hello\r\n");//心跳包
Delay300ms();
Delay300ms();
Time0_init();//初始化定时器0
UartInit();//串口初始化
}
}
void Time0Handler() interrupt 1 //定时器0中断处理
{
cnt++;
TL0=0x33;//重新赋初值
TH0=0xFE;
if(cnt<jd){
sg90_con=1;//模拟pwm脉冲
}else{
sg90_con=0;
}
if(cnt==40){//爆表40次,20ms
cnt=0;
sg90_con=1;
}
}
void Uart_handle() interrupt 4 //串口中断处理
{
static int i=0;//静态变量,初始化1次
if(RI==1){ //中断函数中对接收中断的响应
RI=0; //RI为接受中断数据标志位,接收完数据硬件置1,需要软件置0
cmd[i]=SBUF;
i++; //在SBUF里读取发送的数据
if(i==SIZE){
i=0;
}
if(strstr(cmd,"open")){ //strstr(str1,str2)判断str1里面是不是有str2
led1=0;//灯光调试
jd=8;
cnt=0;
i=0;
memset(cmd,'\0',SIZE);//memset是将某一块内存中的内容全部设置为指定的值
}
if(strstr(cmd,"close")){
led1=1;
cnt=0;
jd=1;
i=0;
memset(cmd,'\0',SIZE);
}
}
}
四、实现效果
![](https://img-blog.csdnimg.cn/img_convert/b20eb67bd4375d271d9bec152e78f250.jpeg)