简述:学校的一个实践项目,采用GPRS+GPRS+红外+传统家电和C语言开发实现对现有家电的远程控制。
硬件:STM32F103(普中版)+GPRS模块(GPRS A6某宝)+红外模块(IR_01某宝)
开发工具和语言:Keil 4 for arm、C
(PS:嵌入式偏软方向,重心放在了代码编写和调试,所以硬件都买现有模块,而并非自绘自制,硬件贴图说明)
细节介绍:通过对STM32的GPIO串口编程,控制GPRS模块进行SMS短信收发和红外模块对红外信号的识别发射,即手机和GPRS模块通过短信、GPRS模块和红外模块通过stm32的GPIO、红外模块和家电通过自识别信号完成远程控制。
功能过程介绍:以格力空调为例,用STM32的按键控制打开红外的识别模式,系统记录下遥控器的红外发射码,对相应的控制码进行编号,以对应不同的短信内容,最终实现手机发送不同内容短信代替遥控器完成对空调的控制。
完成情况:完成了发送短信控制空调打开并调节到相应的温度,空调成功执行并返回对应的短信给手机。(后有实物图,PS:附件项目生成的执行文件烧至stm32即可直接使用)
编码设计&&功能图:
GPRS果云A6实物图:
GPRS果云A6接口图:
红外模块IR_01实物&接口图:
结果图:
附件:
STM32自带的库函数:库函数传送门
GPRS的附带源代码:GPRS源码传送门
项目完整代码:项目源码传送门
重点代码分析:
/**********************************************************************************
STM32F103C8T6
GSM 短信控制
* 硬件连接说明
使用单片串口2与GPRS模块通信 注:使用串口2可以避免下载和通信不会冲突
STM32 GPRS模块
PA3(RXD2) ->RXD
PA2(TXD2) ->TXD
GND ->GND
STM32 IR01模块
PA9(RXD2) ->RXD
PA10(TXD2)->TXD
GND ->GND
**********************************************************************************/
#include "stm32f10x.h"
#include "usart.h"
#include "Led.h"
#include "SysTick.h"
#include "timer.h"
#include "string.h"
#include "key.h"
#define Automatic_Startup 1 //定义自启动 V1.2版本起有自启动功能
#define Buf1_Max 60 //串口1缓存长度
#define Buf2_Max 200 //串口2缓存长度
/************* 本地常量声明 **************/
//红外模块的初始化、学习和发射码值
char Uart1_test[10]={0x7E,0x05,0x00,0x53,0x31,0x53,0x31,0x01,0x8c};
char Uart1_open[11]={0x7E,0x07,0x00,0x53,0x31,0x53,0x31,0x14,0x01,0x00,0xA2};
char Uart1_close[11]={0x7E,0x07,0x00,0x53,0x31,0x53,0x31,0x14,0x02,0x00,0xA3};
char Uart1_study1[11]={0x7E,0x07,0x00,0x53,0x31,0x53,0x31,0x12,0x06,0x00,0xA5};
char Uart1_send1[11]={0x7E,0x07,0x00,0x53,0x31,0x53,0x31,0x14,0x06,0x00,0xA7};
char Uart1_study2[11]={0x7E,0x07,0x00,0x53,0x31,0x53,0x31,0x12,0x07,0x00,0xA6};
char Uart1_send2[11]={0x7E,0x07,0x00,0x53,0x31,0x53,0x31,0x14,0x07,0x00,0xA8};
static unsigned char *GSM_Way="GSM"; //短信中心号设置
static unsigned char *phone="189xxxx5962"; //短信接收方手机号
static unsigned char *content1="AC Key1 Success!";//发送短信内容
static unsigned char *content2="AC Key2!";//发送短信内容
static unsigned char *content3="AC Key3 Mode!";//发送短信内容
/************* 本地变量声明 **************/
char Uart1_Buf[Buf1_Max];
char Uart2_Buf[Buf2_Max];
u8 Times=0,First_Int = 0,shijian=0;
vu8 Timer0_start; //定时器0延时启动计数器
vu8 Uart2_Start; //串口2开始接收数据
vu8 Uart2_End; //串口2接收数据结束
/************* 本地函数声明 **************/
void CLR_Buf2(void);
void CLR_Buf1(void);
u8 Find(char *a);
void Second_AT_Command(char *b,u8 wait_time);
void Set_Text_Mode(void);
void Check_New_Message(void);
void Wait_CREG(void);
void Key_Pros(void);
void Send_Text_Sms(void);
void Send_Text_Sms2(void);
void Send_Text_Sms3(void);
/*******************************************************************************
* 函数名 : main
* 描述 : 主函数
* 输入 :
* 输出 :
* 返回 :
* 注意 : 串口2负责与GPRS模块通信,串口1用于串口调试,可以避免在下载程序时数据
还发送到模块
*******************************************************************************/
int main(void)
{
SysTick_Init_Config();
GPIO_Config();
Key_GPIO_Config();
USART1_Init_Config(9600);
USART2_Init_Config(9600);
Timer2_Init_Config();
UART1_SendString("\r\n");
UART1_SendString("GPRS模块短信测试程序\r\n");
UART1_SendString("GPRS模块在注册网络\r\n");
Wait_CREG();
UART1_SendString("GPRS模块注册成功\r\n");
UART1_SendString("GPRS模块短信模式设置\r\n");
Set_Text_Mode();
UART1_SendString("设置成功,短信模式:TEXT\r\n");
UART1_SendString("初始化完成\r\n");
LED7_ON();
while(1)
{
Check_New_Message();
}
}
/*******************************************************************************
* 函数名 : Second_AT_Command
* 描述 : 发送AT指令函数
* 输入 : 发送数据的指针、希望接收到的应答数据指针、发送等待时间(单位:S)
* 输出 : 无
* 返回 : 无
* 注意 : 无
*******************************************************************************/
void Second_AT_Send(char *b,char *a,u8 wait_time)
{
u8 i;
char *c;
c = b; //保存字符串地址到c
CLR_Buf2();
i = 0;
while(i == 0)
{
if(!Find(a))
{
if(Timer0_start == 0)
{
b = c;
for (; *b!='\0';b++)
{
while(USART_GetFlagStatus(USART2, USART_FLAG_TC)==RESET);
USART_SendData(USART2,*b);
}
UART2_SendLR();
Times = 0;
shijian = wait_time;
Timer0_start = 1;
}
}
else
{
i = 1;
Timer0_start = 0;
}
}
CLR_Buf2();
}
/*******************************************************************************
* 函数名 : Send_Text_Sms
* 描述 : 发送TEXT文本短信
* 输入 : 无
* 输出 : 无
* 返回 : 无
* 注意 : 无
*******************************************************************************/
void Send_Text_Sms(void)
{
char temp[50]="AT+CMGS=";
strcat(temp,(char*)phone); //字符串拼接函数
Second_AT_Send(temp,">",3); //等待接收到“>”才发送短信内容
UART2_SendString((char*)content1); //发送短信内容
USART_SendData(USART2 ,0X1A); //发送结束符
UART2_SendLR();
}
void Send_Text_Sms2(void)
{
char temp[50]="AT+CMGS=";
strcat(temp,(char*)phone);
Second_AT_Send(temp,">",3);
UART2_SendString((char*)content2);
USART_SendData(USART2 ,0X1A);
UART2_SendLR();
}
void Send_Text_Sms3(void)
{
char temp[50]="AT+CMGS=";
strcat(temp,(char*)phone);
Second_AT_Send(temp,">",3);
UART2_SendString((char*)content3);
USART_SendData(USART2 ,0X1A);
UART2_SendLR();
}
/*******************************************************************************
* 函数名 : 按键测试函数
* 描述 : 进行按键检测
* 输入 : 无
* 返回 : 无
* 说明 : 调试过程中的按键测试
*******************************************************************************/
void Key_Pros(void)
{
u8 i;
if(keyup==1)
{
Delay_nMs(10);
if(keyup==1)
{
LED6_ON();
LED2_OFF();
LED3_OFF();
LED4_OFF();
for(i=0;i<9;i++)
{
UART1_SendChar(Uart1_test[i]);
}
UART1_SendString("\r\n");
}
while(keyup);
}
if(key1==0)
{
Delay_nMs(10);
if(key1==0)
{
LED1_ON();
LED2_OFF();
LED3_OFF();
LED4_OFF();
for(i=0;i<11;i++)
{
UART1_SendChar(Uart1_study1[i]);
}
UART1_SendString("\r\n");
}
while(!key1);
}
if(key2==0)
{
Delay_nMs(10);
if(key2==0)
{
LED2_ON();
LED3_OFF();
LED1_OFF();
LED4_OFF();
for(i=0;i<11;i++)
{
UART1_SendChar(Uart1_study2[i]);
}
UART1_SendString("\r\n");
}
while(!key2);
}
if(key3==0)
{
Delay_nMs(10);
if(key3==0)
{
LED3_ON();
LED2_OFF();
LED1_OFF();
LED4_OFF();
for(i=0;i<11;i++)
{
UART1_SendChar(Uart1_send1[i]);
}
UART1_SendString("\r\n");
}
while(!key3);
}
}
/*******************************************************************************
* 函数名 : USART2_IRQHandler
* 描述 : 串口1中断服务程序
* 输入 : 无
* 返回 : 无
* 说明 :
*******************************************************************************/
void USART2_IRQHandler(void)
{
u8 Res=0;
Res =USART_ReceiveData(USART2);
Uart2_Buf[First_Int] = Res; //将接收到的字符串存到缓存中
First_Int++; //缓存指针向后移动
if(First_Int > Buf2_Max) //如果缓存满,将缓存指针指向缓存的首地址
{
First_Int = 0;
}
}
/*******************************************************************************
* 函数名 : TIM2_IRQHandler
* 描述 : 定时器2中断断服务函数
* 输入 : 无
* 输出 : 无
* 返回 : 无
* 说明 : 无
*******************************************************************************/
void TIM2_IRQHandler(void) //TIM3中断
{
static u8 flag =1;
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) //检查TIM3更新中断发生与否
{
TIM_ClearITPendingBit(TIM2, TIM_IT_Update ); //清除TIMx更新中断标志
if(Timer0_start)
Times++;
if(Times > shijian)
{
Timer0_start = 0;
Times = 0;
}
if(flag)
{
LED8_ON();
flag=0;
}
else
{
LED8_OFF();
flag=1;
}
}
}
/*******************************************************************************
* 函数名 : CLR_Buf2
* 描述 : 清除串口2缓存数据
* 输入 :
* 输出 :
* 返回 :
* 注意 :
*******************************************************************************/
void CLR_Buf2(void)
{
u16 k;
for(k=0;k
一个月的实践,大把时间用在了测试,还有我那测试用的短信费用,啊,为什么要取消套餐内短信费用。。。
时间原因,完成了系统的空调测试用例,没有添加电视热水器等电器的测试,或者可以继续添加非红外控制的家电,待扩展吧。
有哪些不足或者需要改进,请看官给予指正咯。
(PS:个人原创,转发请注明:http://blog.csdn.net/kull_zh/article/details/78140767)