找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3840|回复: 2
收起左侧

单片机智能家居安防系统设计 GSM通讯程序

  [复制链接]
ID:653478 发表于 2019-12-8 20:42 | 显示全部楼层 |阅读模式
1、可检测火焰光源;
2、可检测非法入室的人员;
3、可检测可燃气体;
4、发生以上事故可将报警信息远程传输到户主手机上
51hei.png
单片机源程序如下:
  1. #include "config.h"
  2. #include "string.h"
  3. #include "delay.h"
  4. #include "uart.h"


  5. #define Buf1_Max 200                                           //串口2缓存长度
  6. /*************        本地常量声明        **************/
  7. sbit RUNING_LED = P2^7;                                        //运行指示灯
  8. sbit HW = P1^6;                                        //运行指示灯

  9. static unsigned char *content="8D706C344E86002C5FEB6551706B0021";//发送短信内容  走水了,快救火!
  10. /*************  本地变量声明        **************/

  11. xdata u8 Uart1_Buf[Buf1_Max];

  12. u8 Times=0,First_Int = 0,shijian=0;

  13. bdata u8 Flag;//定时器标志位
  14. sbit Timer0_start =Flag^0;        //定时器0延时启动计数器



  15. /*************        本地函数声明        **************/
  16. void GPIO_config(void); //端口初始化配置
  17. void Timer0Init(void);  //定时器0初始化
  18. void CLR_Buf1(void);    //清除串口2接收缓存
  19. u8 Find(u8 *a);         //查找字符串
  20. void Second_AT_Command(u8 *b,u8 *a,u8 wait_time); //发送AT指令函数
  21. void Set_Pdu_Mode(void);//设置短信模式PDU
  22. void Wait_CREG(void);   //查询等待模块注册成功
  23. void Send_Pdu_Sms(void);//发送一条中文短信
  24. /*************  外部函数和变量声明*****************/



  25. u8 yushe_wendu=50;                                //温度预设值
  26. u16 wendu;                                                                 //温度值全局变量
  27. u8 yushe_yanwu=45;                                //烟雾预设值
  28. u8 yanwu;                                                                 //用于读取ADC数据

  29. //运行模式  
  30. u8 Mode=0;                                                                 //=1是设置温度阀值  =2是设置烟雾阀值        =0是正常监控模式

  31. void Init_Timer0(void);
  32. bit ReadTempFlag;//定义读时间标志


  33. //管脚声明
  34. //sbit Led_Reg                 =P2^7;                                 //红灯
  35. sbit Buzzer             =P3^3;                                 //蜂鸣器
  36. sbit DQ = P1^0;                                 //ds18b20的数据引脚
  37. #define   SMG_NUM   4
  38. u8 code DisplayNum[16]={
  39. 0xc0,                //0
  40. 0xf9,                //1
  41. 0xa4,                //2
  42. 0xb0,                //3
  43. 0x99,                //4
  44. 0x92,                //5
  45. 0x82,                //6
  46. 0xf8,                //7
  47. 0x80,                //8
  48. 0x90,                //9
  49. 0x88,                //A
  50. 0x83,                //b
  51. 0xc6,                //C
  52. 0xa1,                //d
  53. 0x86,                //E
  54. 0x8e                //F
  55. };
  56. //对应关系取字:        dp g f e    d c b a
  57. //例如  U             1  1 0 0    0 0 0 1
  58. u8 code DisplayOther[]={
  59. 0xff,                 //0                空
  60. 0x7f,                 //1                "."
  61. 0xbf,                        //2                "-"
  62. 0xa7,                        //3                c
  63. 0xC1,                        //4                U  
  64. ~0x6e                        //5                y  
  65. };

  66. /********************************************************************
  67. * 名称 : delay_1ms()
  68. * 功能 : 延时1ms函数
  69. * 输入 : q
  70. * 输出 : 无
  71. ***********************************************************************/
  72. void delay1_ms(u16 q)
  73. {
  74.         u16 i,j;
  75.         for(i=0;i<q;i++)
  76.                 for(j=0;j<110;j++);
  77. }
  78. //数码管位选定义
  79. sbit smg_we1 = P2^0;            //
  80. sbit smg_we2 = P2^1;                        //
  81. sbit smg_we3 = P2^2;                        //
  82. sbit smg_we4 = P2^3;                        //


  83. /***********************数码位选函数*****************************/

  84. void smg_we_switch(u8 i)
  85. {
  86.         smg_we1 = 1;
  87.   smg_we2 = 1;
  88.         smg_we3 = 1;
  89.   smg_we4 = 1;
  90.         switch(i)
  91.         {
  92.                 case 0: smg_we1 = 0;   break;
  93.                 case 1: smg_we2 = 0;   break;
  94.                 case 2: smg_we3 = 0;   break;
  95.                 case 3: smg_we4 = 0;   break;
  96.         }        
  97. }


  98. /********************************************************************
  99. * 名称 : u8 ChangeFor(u8 dat)
  100. * 功能 : 交换一个字节位的位置,用于数码管显示
  101. * 输入 : 需要改变的数
  102. * 输出 : 改变后的数
  103. ***********************************************************************/
  104. #define LED_a                0        //数码管段选的a段接在段选IO口的第0位
  105. #define LED_b                2
  106. #define LED_c                6
  107. #define LED_d                4
  108. #define LED_e                3
  109. #define LED_f                1
  110. #define LED_g                7
  111. #define LED_dp        5

  112. u8 ChangeFor(u8 dat)
  113. {
  114.         u8 temp=0;
  115.         if(dat&0x01)                //判断数据的第一位是否为1
  116.                 temp|=0x01<<LED_a;//如果为1,放到控制数码管a段的位置
  117.         if(dat&0x02)
  118.                 temp|=0x01<<LED_b;
  119.         if(dat&0x04)
  120.                 temp|=0x01<<LED_c;
  121.         if(dat&0x08)
  122.                 temp|=0x01<<LED_d;
  123.         if(dat&0x10)
  124.                 temp|=0x01<<LED_e;
  125.         if(dat&0x20)
  126.                 temp|=0x01<<LED_f;
  127.         if(dat&0x40)
  128.                 temp|=0x01<<LED_g;
  129.         if(dat&0x80)
  130.                 temp|=0x01<<LED_dp;
  131.         return temp;
  132. }
  133. u8 dis_smg[SMG_NUM];                                                //显示缓存数组

  134. /********************************************************************
  135. * 名称 : display()
  136. * 功能 : 数码管显示
  137. * 输入 : 无
  138. * 输出 : 无
  139. ***********************************************************************/
  140. void DisplayScan()
  141. {
  142.         static u8 i;
  143.         P0 = 0xff;                  //消隐
  144.                 smg_we_switch(i);                                    //位选
  145.         P0 =        ChangeFor(dis_smg[i]);                  //段选         
  146.         i++;
  147.         if(i>=SMG_NUM)
  148.                 i=0;
  149. }

  150. /*****延时子程序:该延时主要用于ds18b20延时*****/
  151. void Delay_DS18B20(int num)
  152. {
  153.   while(num--) ;
  154. }
  155. /*****初始化DS18B20*****/
  156. void Init_DS18B20(void)
  157. {
  158.   unsigned char x=0;
  159.   DQ = 1;         //DQ复位
  160.   Delay_DS18B20(8);    //稍做延时
  161.   DQ = 0;         //单片机将DQ拉低
  162.   Delay_DS18B20(80);   //精确延时,大于480us
  163.   DQ = 1;         //拉高总线
  164.   Delay_DS18B20(14);
  165.   x = DQ;           //稍做延时后,如果x=0则初始化成功,x=1则初始化失败
  166.   Delay_DS18B20(20);
  167. }
  168. /*****读一个字节*****/
  169. unsigned char ReadOneChar(void)
  170. {
  171.   unsigned char i=0;
  172.   unsigned char dat = 0;
  173.   for (i=8;i>0;i--)
  174.   {
  175.          ET0=0;           //定时器中断关闭
  176.     DQ = 0;     // 给脉冲信号
  177.     dat>>=1;
  178.     DQ = 1;     // 给脉冲信号
  179.     if(DQ)
  180.     dat|=0x80;
  181.     Delay_DS18B20(4);
  182.         ET0=1;           //定时器中断打开
  183.   }
  184.   return(dat);
  185. }
  186. /*****写一个字节*****/
  187. void WriteOneChar(unsigned char dat)
  188. {
  189.   unsigned char i=0;
  190.   for (i=8; i>0; i--)
  191.   {
  192.          ET0=0;           //定时器中断关闭
  193.     DQ = 0;
  194.     DQ = dat&0x01;
  195.     Delay_DS18B20(5);
  196.     DQ = 1;
  197.     dat>>=1;
  198.                 ET0=1;           //定时器中断打开
  199. }
  200. }
  201. u8 tempflag=0; //负号显示
  202. /*****读取温度*****/
  203. unsigned int ReadTemperature(void)
  204. {
  205.   unsigned char a=0;
  206.   unsigned char b=0;
  207.   unsigned int t=0;
  208.   u8 tt=0;
  209.   u8 ttt=0;
  210.   Init_DS18B20();
  211.   WriteOneChar(0xCC);  //跳过读序号列号的操作
  212.   WriteOneChar(0x44);  //启动温度转换
  213.   Init_DS18B20();
  214.   WriteOneChar(0xCC);  //跳过读序号列号的操作
  215.   WriteOneChar(0xBE);  //读取温度寄存器
  216.   a=ReadOneChar();     //读低8位
  217.   b=ReadOneChar();    //读高8位
  218.   t=b;
  219.   t<<=8;
  220.   t=t|a;                                                        //合并高低位为一个字节
  221.         
  222.   tt=(u8)(t>>4);                                                                        //得到整数位
  223.         ttt=(u8)((t%16)*0.0625*10);                        //得到小数位;乘以10代表保留一位小数;
  224.         if(tt&0x80)
  225.         {
  226.                 tempflag=1; //负号显示
  227.                 tt=~tt+1; //实际温度值为读取值的补码
  228.         }
  229.         else
  230.                 tempflag=0; //正号显示
  231.   t= tt*10+ttt;                                                             //放大10倍
  232.   return(t);
  233. }


  234. /*****校准温度*****/
  235. u16 check_wendu(void)
  236. {
  237.         u16 c;
  238.         c=ReadTemperature();                          //获取温度值并减去DS18B20的温漂误差
  239.         return c;
  240. }

  241. //按键
  242. sbit Key1=P1^6;                                 //设置键
  243. sbit Key2=P1^7;                                 //加按键
  244. sbit Key3=P3^2;                                 //减按键
  245. #define KEY_SET                 1                //设置
  246. #define KEY_ADD                        2                //加
  247. #define KEY_MINUS                3                //减
  248. //========================================================================
  249. // 函数: u8 Key_Scan()
  250. // 应用: temp=u8 Key_Scan();
  251. // 描述: 按键扫描并返回按下的键值
  252. // 参数: NONE
  253. // 返回: 按下的键值
  254. // 版本: VER1.0
  255. // 日期: 2015-05-29
  256. // 备注: 该函数带松手检测,按下键返回一次键值后返回0,直至第二次按键按下
  257. //========================================================================
  258. u8 Key_Scan()
  259. {         
  260.         static u8 key_up=1;//按键按松开标志
  261.         if(key_up&&(Key1==0||Key2==0||Key3==0))
  262.         {
  263.                 delay1_ms(10);//去抖动
  264.                 key_up=0;
  265.                 if(Key1==0)                        return 1;
  266.                 else if(Key2==0)return 2;
  267.                 else if(Key3==0)return 3;
  268.         }
  269.         else if(Key1==1&&Key2==1&&Key3==1)
  270.                 key_up=1;            
  271.          return 0;// 无按键按下
  272. }

  273. /***********************************************************************************************************
  274. ADC0832相关函数
  275. ***********************************************************************************************************/
  276. sbit AD0832_CS   = P1^5 ;   //片选信号
  277. sbit AD0832_CLK  = P1^2;    //时钟接口
  278. sbit AD0832_DI   = P1^3;    //数据接口  /*因为单片机的管脚是双向的,且ADC0832的数据输入输出不同时进行,为节省单片机引脚,简化电路所以输入输出连接在同一个引脚上*/
  279. u8 GetAD0832(bit Channel)
  280. {     
  281.         u8  i=0 , Data1 =0 , Data2 = 0 ;     
  282.         AD0832_CLK = 0 ;        //时钟置低平//时钟12Mhz, 整个转换时间为224us  
  283.         //使用芯片准备(参考PDF时序图)      
  284.         AD0832_DI  = 1 ;        //开始信号为高电平     
  285.         AD0832_CS  = 0 ;        //片选信号置低,启动AD转换芯片            
  286.         AD0832_CLK = 1 ;        //输入开始信号(构成一个正脉冲),时钟上升沿,输入开始信号     
  287.         AD0832_CLK = 0 ;        //时钟下降沿   
  288.         //模拟信号输入模式选择(1:单模信号,0:双模差分信号)   
  289.         AD0832_DI  = 1 ;     
  290.         AD0832_CLK = 1 ;        //时钟上升沿,输入开始信号     
  291.         AD0832_CLK = 0 ;        //时钟下降沿     
  292.         //模拟信号输入通道选择(1:通道CH1,0:通道CH0)   
  293.         AD0832_DI  = Channel ;  //选择通道0     
  294.         AD0832_CLK = 1;         //时钟上升沿,输入开始信号
  295.         AD0832_CLK = 0;         //时钟下降沿         
  296.         AD0832_DI  = 1;                      //数据线置高,准备接收数据  
  297.         for(i=0;i<8;i++)                          //从高位移入数据   
  298.         {      
  299.                 AD0832_CLK = 1 ;              
  300.                 AD0832_CLK = 0 ;      //时钟下降沿,AD0832输出数据,高位(MSB)先         
  301.                 Data1 = Data1<<1;     //数据左移位,补0     
  302.                 if(AD0832_DI ==1)      
  303.                 {
  304.                         Data1 = Data1 | 0x01;
  305.                 }                                                    //如果数据为“1”,移入1,   
  306.         }                              //如果数据为“0”,移入0,        
  307.         for(i=0;i<8;i++)                     //从低位移入数据  
  308.         {      
  309.                 Data2 = Data2>>1;   //数据左移位,补0     
  310.                 if(AD0832_DI ==1)        
  311.                 {
  312.                         Data2 = Data2 | 0x80;
  313.                 }   //如果数据为“1”,移入1如果数据为“0”,移入0,         
  314.                 AD0832_CLK = 1;            
  315.                 AD0832_CLK = 0;          //时钟下降沿,AD0832输出数据,高位(MSB)先  
  316.         }     
  317.         //数据线置高,释放总线,完成一次转换     
  318.         AD0832_CLK = 1 ;            
  319.         AD0832_DI  = 1;              
  320.         AD0832_CS  = 1;                     
  321.         if(Data1==Data2)     //输出   
  322.         {
  323.                 return Data2;
  324.         }  
  325.         return 0;
  326. }
  327. /*******************************************************************************
  328. * 函数名 : Set_Text_Mode
  329. * 描述   : 设置短信为TEXT文本模式
  330. * 输入   :
  331. * 输出   :
  332. * 返回   :
  333. * 注意   :
  334. *******************************************************************************/
  335. void Set_Text_Mode(void)
  336. {
  337.         Second_AT_Command("ATE0","OK",3);                                                                                  //取消回显        
  338.         Second_AT_Command("AT+CNMI=3,2,0,0,0","OK",3);                                                        //新短信直接输出
  339.         Second_AT_Command("AT+CMGF=1","OK",3);                                                                //TEXT模式        
  340.         Second_AT_Command("AT+CPMS=\"SM\",\"SM\",\"SM\"","OK",3);                //所有操作都在SIM卡中进行        
  341. }

  342. /*******************************************************************************
  343. * 函数名 : main
  344. * 描述   : 主函数
  345. * 输入   :
  346. * 输出   :
  347. * 返回   :
  348. * 注意   : 串口波特率是9600,GPRS模块默认波特率是115200,需要自己通过串口助手修改
  349.                                    为9600方可使用。
  350. *******************************************************************************/
  351. void main(void)
  352. {
  353.         u8 key;
  354.         u8 bj=0;
  355.         u16 i=0;
  356.         Timer0Init();  //初始化定时器0
  357.         dis_smg[0] = DisplayOther[2] ;
  358.         dis_smg[1] = DisplayOther[2] ;
  359.         dis_smg[2] = DisplayOther[2] ;
  360.         dis_smg[3] = DisplayOther[2] ;        
  361.         GPIO_config();
  362.         EA=1;        //开总中断
  363.         Uart1Init();    //初始化串口9600
  364.         Wait_CREG();    //查询等待模块注册成功
  365.         Set_Text_Mode();//设置短信为TEXT模式
  366.         Buzzer=0;                                                  //打开蜂鸣器报警
  367.         wendu=check_wendu();                  //初始化时调用温度读取函数 防止开机85°C
  368.         delay1_ms(1000);
  369.         wendu=check_wendu();                  //初始化时调用温度读取函数 防止开机85°C
  370.         Buzzer=1;                                                  //打开蜂鸣器报警

  371.         while (1)                                                //主循环
  372.         {
  373.                 key=Key_Scan();                                        //按键扫描
  374.                 i++;
  375.                 if(i>=2000)
  376.                 {
  377.                         i=0;
  378.                         wendu=check_wendu();          //读取温度值
  379.                         yanwu=GetAD0832(0)*100/255;                        //读取烟雾值
  380.                 }        
  381.                 if(key==KEY_SET)
  382.                 {
  383.                         Mode++;
  384.                 }
  385.                
  386.                 switch(Mode)                                                //判断模式的值
  387.                 {
  388.                         case 0:                                                                //监控模式
  389.                                 dis_smg[0] = DisplayNum[wendu/100%10] ;        
  390.                                 dis_smg[1] = DisplayNum[wendu/10%10];        
  391.                                 dis_smg[2] = DisplayNum[yanwu/10%10] ;        
  392.                                 dis_smg[3] = DisplayNum[yanwu%10] ;        
  393.                         
  394.                                 if((yanwu<yushe_yanwu)&&(wendu<(yushe_wendu*10)))          //当烟雾小于预设值并且温度也小于预设值时 (&&:逻辑与,左右两边的表达式都成立(都为真,也就是1)时,该if语句才成立)
  395.                                 {
  396.                                         Buzzer=1;                                                  //打开蜂鸣器报警
  397.                                         bj=0;
  398.                                 }
  399.                                 else                                                                                  //温度值小于预设值时
  400.                                 {
  401.                                         Buzzer=0;                                                  //停止报警
  402.                                         if(bj==0)
  403.                                         {
  404.                                                 bj=1;
  405.                                                 Set_Pdu_Mode();//设置短信为PDU模式
  406.                                                 Send_Pdu_Sms();//发送一条短消息
  407.                                         }
  408.                                 }
  409.                                 break;
  410.                         case 1://预设温度模式
  411.                         {
  412.                                 dis_smg[0] = DisplayNum[0xc];        
  413.                                 dis_smg[1] = DisplayOther[2] ;        
  414.                                 dis_smg[2] = DisplayNum[yushe_wendu/10%10];        
  415.                                 dis_smg[3] = DisplayNum[yushe_wendu%10] ;        
  416.                                 if(key==KEY_ADD)                                                        //加键按下
  417.                                 {
  418.                                         yushe_wendu++;                                            //预设温度值(阀值)加1
  419.                                         if(yushe_wendu>=99)                                         //当阀值加到大于等于99时
  420.                                         yushe_wendu=99;                                                         //阀值固定为99
  421.                                 }
  422.                                 if(key==KEY_MINUS)                                                 //减键按下
  423.                                 {
  424.                                         if(yushe_wendu<=1)                                        //当温度上限值减小到1时
  425.                                         yushe_wendu=1;                          //固定为1
  426.                                         yushe_wendu--;                                                        //预设温度值减一,最小为0
  427.                                 }
  428.                                 break;                                                                                          //执行后跳出switch
  429.                         }
  430.                         case 2://预设烟雾模式
  431.                         {
  432.                                 dis_smg[0] = DisplayOther[5];        
  433.                                 dis_smg[1] = DisplayOther[2] ;        
  434.                                 dis_smg[2] = DisplayNum[yushe_yanwu/10%10];        
  435.                                 dis_smg[3] = DisplayNum[yushe_yanwu%10] ;        
  436.                                 if(key==KEY_ADD)                                                        //加键按下
  437.                                 {
  438.                                         yushe_yanwu++;                                            //预设温度值(阀值)加1
  439.                                         if(yushe_yanwu>=99)                                         //当阀值加到大于等于99时
  440.                                         yushe_yanwu=99;                                                         //阀值固定为99
  441.                                 }
  442.                                 if(key==KEY_MINUS)                                                 //减键按下
  443.                                 {
  444.                                         if(yushe_yanwu<=1)                                        //当温度上限值减小到1时
  445.                                         yushe_yanwu=1;                          //固定为1
  446.                                         yushe_yanwu--;                                                        //预设温度值减一,最小为0
  447.                                 }
  448.                                 break;                                                                                          //执行后跳出switch
  449.                         }

  450.                         default        :        
  451.                         {
  452.                                 Mode=0;                        //恢复正常模式
  453.                                 break;
  454.                         }
  455.                 }
  456.         
  457.         }
  458.         
  459. }

  460. /*******************************************************************************
  461. * 函数名 : Uart1
  462. * 描述   : 串口1中断服务入口函数
  463. * 输入   :
  464. * 输出   :
  465. * 返回   :
  466. * 注意   :
  467. *******************************************************************************/
  468. void Uart1() interrupt 4
  469. {
  470.     if (RI)
  471.     {
  472.       RI = 0;                 //清除RI位
  473.                         Uart1_Buf[First_Int] = SBUF;            //将接收到的字符串存到缓存中
  474.                         First_Int++;                                        //缓存指针向后移动
  475.                         if(First_Int > Buf1_Max)                       //如果缓存满,将缓存指针指向缓存的首地址
  476.                         {
  477.                                 First_Int = 0;
  478.                         }
  479.     }
  480.     if (TI)
  481.     {
  482.         TI = 0;                 //清除TI位
  483.     }
  484. }
  485. /*******************************************************************************
  486. * 函数名 : Timer0_ISR
  487. * 描述   : 定时器0中断服务入口函数,20ms中断一次
  488. * 输入   :
  489. * 输出   :
  490. * 返回   :
  491. * 注意   :
  492. *******************************************************************************/
  493. void Timer0_ISR() interrupt 1
  494. {
  495.         static u16 Time_count=0;
  496.         static u8 i=0;
  497.         TL0 = 0xCD;                //设置定时初值
  498.         TH0 = 0xF8;                //设置定时初值
  499.         TR0=0;//关定时器
  500.         DisplayScan();// 调用数码管扫描
  501.         i++;
  502.         if(i>=10)
  503.         {
  504.                 i=0;
  505.                 Time_count++;
  506.                 if(Time_count>=50)
  507.                 {
  508.                         Time_count = 0;
  509.                         RUNING_LED =~RUNING_LED;
  510.                 }
  511.                 if(count_20ms) //20ms延时计数器
  512.                         count_20ms--;
  513.                 if(Timer0_start)
  514.                 Times++;
  515.                 if(Times > (50*shijian))
  516.                 {
  517.                         Timer0_start = 0;
  518.                         Times = 0;
  519.                 }
  520.         }
  521.         TR0=1;//开定时器
  522. }
  523. /*******************************************************************************
  524. * 函数名 : GPIO_config
  525. * 描述   : IO口配置函数
  526. * 输入   :
  527. * 输出   :
  528. * 返回   :
  529. * 注意   :
  530. *******************************************************************************/
  531. void        GPIO_config(void)
  532. {
  533.                 RUNING_LED=0;
  534. }
  535. /*******************************************************************************
  536. * 函数名 : Timer0Init
  537. * 描述   : 定时器0初始化,20ms定时
  538. * 输入   :
  539. * 输出   :
  540. * 返回   :
  541. * 注意   :
  542. *******************************************************************************/
  543. void Timer0Init(void)                //20毫秒@11.0592MHz
  544. {
  545.         AUXR &= 0x7F;                //定时器时钟12T模式
  546.         TMOD &= 0xF0;                //
  547.         TMOD |= 0x01;                //设置定时器模式,16位定时器
  548.         TL0 = 0xCD;                //设置定时初值
  549.         TH0 = 0xF8;                //设置定时初值
  550.         TF0 = 0;                    //清TF0标志
  551.         TR0 = 1;                    //定时器0开始计时
  552.         ET0 = 1;              //使能定时器0中断
  553. }
  554. /*******************************************************************************
  555. * 函数名 : CLR_Buf1
  556. * 描述   : 清除串口2缓存数据
  557. * 输入   :
  558. * 输出   :
  559. * 返回   :
  560. * 注意   :
  561. *******************************************************************************/
  562. void CLR_Buf1(void)
  563. {
  564.         u16 k;
  565.         for(k=0;k<Buf1_Max;k++)      //将缓存内容清零
  566.         {
  567.                 Uart1_Buf[k] = 0x00;
  568.         }
  569.     First_Int = 0;              //接收字符串的起始存储位置
  570. }

  571. /*******************************************************************************
  572. * 函数名 : Find
  573. * 描述   : 判断缓存中是否含有指定的字符串
  574. * 输入   :
  575. * 输出   :
  576. * 返回   : unsigned char:1 找到指定字符,0 未找到指定字符
  577. * 注意   :
  578. *******************************************************************************/

  579. u8 Find(u8 *a)
  580. {
  581.   if(strstr(Uart1_Buf,a)!=NULL)
  582.             return 1;
  583.         else
  584.                         return 0;
  585. }

  586. /*******************************************************************************
  587. * 函数名 : Second_AT_Command
  588. * 描述   : 发送AT指令函数
  589. * 输入   : 发送数据的指针、发送等待时间(单位:S)
  590. * 输出   :
  591. * 返回   :
  592. * 注意   :
  593. *******************************************************************************/

  594. void Second_AT_Command(u8 *b,u8 *a,u8 wait_time)         
  595. {
  596.         u8 i;
  597.         u8 *c;
  598.         c = b;                                                                                //保存字符串地址到c
  599.         CLR_Buf1();
  600.   i = 0;
  601.         while(i == 0)                    
  602.         {
  603.                 if(!Find(a))           //查找需要应答的字符
  604.                 {
  605.                         if(Timer0_start == 0)//超时重新发送命令
  606.                         {
  607.                                 b = c;                                                 //将字符串地址给b
  608.                                 for (b; *b!='\0';b++)
  609.                                 {
  610.                                         UART1_SendData(*b);
  611.                                 }
  612.                                 UART1_SendLR();        
  613.                                 Times = 0;
  614.                                 shijian = wait_time;
  615.                                 Timer0_start = 1;  //开始计时
  616.                    }
  617.     }
  618.            else
  619.                 {
  620.                         i = 1;
  621.                         Timer0_start = 0;  
  622.                 }
  623.         }
  624.         CLR_Buf1();
  625. }

  626. /*******************************************************************************
  627. * 函数名 : Set_Pdu_Mode
  628. * 描述   : 设置短信为TEXT文本模式
  629. * 输入   :
  630. * 输出   :
  631. * 返回   :
  632. * 注意   :
  633. *******************************************************************************/
  634. void Set_Pdu_Mode(void)
  635. {
  636.         Second_AT_Command("ATE0","OK",3);                                                                                  //取消回显        
  637.         Second_AT_Command("AT+CMGF=1","OK",3);                                                                //设置为文本模式        
  638.         Second_AT_Command("AT+CSMP=17,167,2,25","OK",3);      //设置文本模式参数
  639. }
  640. /*******************************************************************************
  641. * 函数名 : Send_Pdu_Sms
  642. * 描述   : 发送PDU文本短信
  643. * 输入   :
  644. * 输出   :
  645. * 返回   :
  646. * 注意   :
  647. *******************************************************************************/
  648. void Send_Pdu_Sms(void)
  649. {

  650.         Second_AT_Command("AT+CSCS=\"UCS2\"","OK",3); //设置为 UCS2 编码字符集
  651.         Second_AT_Command("AT+CMGS=\"00310033003200340033003100360031003500360035\"",">",3);
  652.         UART1_SendString(content);     //发送短信内容
  653.         UART1_SendData(0X1A);          //发送结束符
  654. }

  655. /*******************************************************************************
  656. * 函数名 : Wait_CREG
  657. * 描述   : 等待模块注册成功
  658. * 输入   :
  659. * 输出   :
  660. * 返回   :
  661. * 注意   :
  662. *******************************************************************************/
  663. void Wait_CREG(void)
  664. {
  665.         u8 i;
  666.         u8 k;
  667.         i = 0;
  668.         CLR_Buf1();
  669.   while(i == 0)                                
  670.         {
  671.                 CLR_Buf1();        
  672.                 UART1_SendString("AT+CREG");//查询模块网络注册状态
  673.                 UART1_SendLR();
  674.                 delay_ms(250);                                                  
  675.             for(k=0;k<Buf1_Max;k++)                              
  676.             {
  677.                         if(Uart1_Buf[k] == ':')
  678.                         {
  679.                                 if((Uart1_Buf[k+4] == '2')||(Uart1_Buf[k+4] == '5')) //表明网络注册成功
  680.                                 {
  681.                                         i = 1;
  682.                                   break;
  683.                                 }
  684.                         }
  685.                 }
  686.         }
  687. }
复制代码

原理图,代码: 定做资料.zip (432.64 KB, 下载次数: 190)
回复

使用道具 举报

ID:653478 发表于 2019-12-8 20:44 | 显示全部楼层
电路图,程序
回复

使用道具 举报

ID:1100989 发表于 2024-2-21 16:12 | 显示全部楼层

打开原理图的软件可以仿真吗
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表