⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gsm12051.c

📁 GSM在单片机开发中的应用 和一些器件的应用程序 24c04 键盘编程
💻 C
字号:
#include<reg51.h>
#include<intrins.h>
#define uchar  unsigned char
#define uint   unsigned int
#define TRUE   1
#define FALSE  0
//#define SEND_TO_GSM

void  init(void);
bit   Send_Gsm(void);         //通过GSM返回信息用   接收采用中断
void  Display(void);         //7段显示
void  Change_and_Save(void); // 对速度进行转化 和 保存
void  delay_10ms(uint x);
void  watch_dog(void);
bit   test_wip(void);
uchar read_out(void);
void  write_in(uchar n);
void  in5045(bit k, uchar m, uchar  *pa, uchar n);
void  out5045(bit k, uchar a, uchar *pa, uchar b);

sbit  SI  = P1^0;   // X5045 用
sbit  SO  = P1^1;
sbit  SCK = P1^2;
sbit  WDI = P1^3;

bit   WAT_DOG;  //中断喂狗允许位
bit   EN_SEND;  //2总线发送允许标记位
bit   EN_RETGSM;  //通过GSM返回短信的标记
bit   COM_TAG;  //串口接收数据超时的标签
bit   COM1_TAG;
uchar Cont_Num; //D7H 后面的控制字
uchar Tell_Num[6];
uchar Speed[6]; //存放速度值缓冲区
uint  Ex_Time;  //系统超时 时间
uint  Ex1_Time;
uchar Send_to_89C51[5];  //为了传输的可靠  扩展到5个字节 最后一个字节规定为和校验

uchar code gsm0[54]=
{
0xD7,0x35,0x01,0x33,0x80,0x89,0x66,0x99,                                 //   电话号码位  0--7
// 0   1     2    3    4    5    6    7
0x96,0x50,0x90,0x1F,0x72,0x4C,                                           //   限速牌
// 8    9   10   11   12   13
0x7F,0x16,0x53,0xF7,0x00,0x3A,0x00,0x3C,                                 //  编号:<
//14   15   16   17   18   19   20   21
0x00,0x41,0x00,0x4A,0x00,0x30,0x00,0x30,0x00,0x31,0x00,0x3E,             //  AJ001 >
//22   23   24   25   26   27   28   29   30   31   32   33
0x90,0x1F,0x5E,0xA6,0x8B,0xBE,0x7F,0x6E,0x00,0x3A,                       //   速度设置:
//34   35  36   37   38   39   40   41   42   43
0x00,0x3C,                                                               //   <
//44   45
0x00,0x31,0x00,0x32,0x00,0x30,                                           //    120
//46   47   48   49   50   51
0x00,0x3E,                                                               //     >
//52   53
};

/***********************************主程序*********************************/
void main(void)
{
  watch_dog();
  delay_10ms(10);  //上电沿时1S  保证外设正常上电工作   看门狗需要设置成1.4S 喂狗
  init();
  out5045(0, 0, Send_to_89C51, 5);
  Display();
  for(;;)
  {
    if(EN_SEND==TRUE)      //任务就绪
    {
      EA=FALSE;  Change_and_Save();
      if(EN_SEND==TRUE)            //速度设置合法
      {
        Display();
        EN_SEND=FALSE;
        EN_RETGSM=TRUE;
      }
      EA=TRUE;
    }
    watch_dog();
    if(EN_RETGSM==TRUE)   //返回短信
    {
      EN_RETGSM=FALSE;
      Send_Gsm();
    }
  }
}

/******************************void init(void)******************************
这里2051主要完成对GSM的接收信息和需要的速度传送给89C51所以这完成串口设置
I/O口的初始化和定时器的初始化.
****************************************************************************/
void init(void)
{
  watch_dog();
  TMOD = 0x21;                /*   设置2个定时器的模式 timer1:2  time0:1  */
  TL1  = 0xfd;
  TH1  = 0xfd;
  SCON = 0x50;                    
  TL0  = 0X00;
  TH0  = 0XDC;
  TR1  = 1;
  TR0  = 1;
  IE   = 0x92;
  PT0  = 1;                             /*    定时器为高优先级    */
  P1   = 0XFF;
  P3   = 0XFF;
  EN_RETGSM = FALSE;
}

/**********************void TIMER0(void) interrupt 1 using 1****************
这为定时器0的中断处理程序。中断函数系统频率,主要用与限时处理,超时出错等.
定时时间为10ms,定时器1用做波特率发生器.
****************************************************************************/
void TIMER0(void) interrupt 1  using 1
{
  TL0 = 0x00;
  TH0 = 0xDC;
  if(--Ex_Time==0)
  {  COM_TAG=0; }
  if(--Ex1_Time==0)
  {  COM1_TAG=0; }
  if(WAT_DOG)
  {  watch_dog(); }
}

/***************************void communications(void)***********************
串口中断函数,用于接收来自GSM的数据.具体使用待定
***************************************************************************/
void communications(void)  interrupt 4  using 2
{
  uchar a;
  watch_dog();
  WAT_DOG=1;
  RI=0;
  if(SBUF!=0xD7)   { WAT_DOG=0; return; }
  Ex_Time = 500;          /*  超时出错  先设置为1200MS */
  COM_TAG = 1;         //接收超时标签
  TL0 = 0x00;
  TH0 = 0xDC;
  while((RI!=1) && (COM_TAG));  RI=0;  //接收控制字
  Cont_Num=SBUF;
 // if(Cont_Num!=0x35)  { WAT_DOG=0; return; }    //if >147    说明是命令 而不是数据
  for(a=0; a<6; a++)          //保存电话号码
  {
    while((RI!=1) && (COM_TAG));  RI=0;
    Tell_Num[a]=SBUF;
  }
  if((Tell_Num[0]!=0x01)||(COM_TAG==FALSE))  { WAT_DOG=0; return; }
  for(a=8; a<46; a++)
  {
    while((RI!=1) && (COM_TAG));  RI=0;
    if((SBUF!=gsm0[a])||(COM_TAG==FALSE))    { WAT_DOG=0; return; }
  }
  for(a=0; a<6; a++)           //存放速度值
  {
    while((RI!=1) && (COM_TAG));  RI=0;
    if(COM_TAG==FALSE)            { WAT_DOG=0; return; }
    else                          { Speed[a]=SBUF; }
  }
  while((RI!=1) && (COM_TAG));  RI=0;
  if(SBUF)  { WAT_DOG=0; return; }
  while((RI!=1) && (COM_TAG));  RI=0;
  if((SBUF!=0x3E)||(COM_TAG==FALSE))  { WAT_DOG=0; return; }
  EN_SEND=TRUE;  //任务就绪
  WAT_DOG=0;
}

/***************************void delay_10ms(uint x)***********************
沿时程序  沿时时间为入口参数 (X*10)ms  无出口参数.
**************************************************************************/
void delay_10ms(uint x)           //使用一个局部变量
{
  uchar b;
  for( ; x>0; x--)
  {
    _nop_();
    for(b=0; b<230; b++)
    {
      _nop_();
      _nop_();  _nop_();
      _nop_();  _nop_();
      _nop_();  _nop_();
      _nop_();  _nop_();
      _nop_();  _nop_();
      _nop_();  _nop_();
      _nop_();  _nop_();
      _nop_();  _nop_();
      _nop_();  _nop_();
      _nop_();  _nop_();
      _nop_();  _nop_();
      _nop_();  _nop_();
      _nop_();  _nop_();
      _nop_();  _nop_();
      _nop_();  _nop_();
      _nop_();  _nop_();
      _nop_();  _nop_();
      _nop_();  _nop_();
    }
  }
}

/**************************uchar read_out(void)*************************
      读字节程序。功能:从x5045存储区读一个字节数据,下降沿有效。
************************************************************************/
uchar read_out(void)
{
  uchar k,f=0;
  SCK=1;
  for(k=0;k<8;k++)
  {
    SCK=1;    //下降触发
    _nop_();
    SCK=0;
    _nop_();
    _nop_();
    f<<=1;
    if(SO) f+=1;
  }
  return(f);
}

/*****************************void  write_in(uchar n)***********************
        写字节程序。功能:传递一个数据写入x5045存储区,上升沿有效。
****************************************************************************/
void  write_in(uchar n)
{
  uchar k;
  WDI=0;
  _nop_();
  _nop_();
  SCK=0;
  for(k=0; k<8; k++)
  {
    if(n&0x80)
    { SI=1; SCK=0; _nop_(); SCK=1; }
    else
    { SI=0; SCK=0; _nop_(); SCK=1; }
    n<<=1;
  } 
}

/************************void out5045(uchar data a,  uchar data b)*****************
           读出x5045存储区指定地址的数据串。功能:k=1为高16页,k=0为低16页,
                  *pa指向入口数据串首地址,a为首地址,b为数据串长度。
**********************************************************************************/
void out5045(bit k, uchar a,  uchar *pa,  uchar b)
{
  uchar i;
  WDI=0;
  if(k)  write_in(0x0b);    //后256字节
  else   write_in(0x03);     //前256字节  READ指令
  write_in(a);
  for(i=0; i<b; i++)
  {
    *pa = read_out();
    pa++;
  }
  WDI=1;
}

/********************void in5045(uchar m, uchar *pa, uchar n)*********************
写数据程序。功能:首先测试内部非易失性写操作位wip位,写数据串到x5034存储区指定地址,
m为存储区地址,pa为数据块首地址,n为要写入的数据块的长度。
**********************************************************************************/
void in5045(bit k, uchar m, uchar  *pa, uchar n)
{
  uchar i;
  while(test_wip());   //测试wip位直到wip为0
  WDI=0;
  write_in(0x06);      //WREN 指令
  WDI=1;
  _nop_();
  _nop_();
  WDI=0;
  if(k) write_in(0x0a);      //选高半地址
  else  write_in(0x02);
  write_in(m);
  for(i=0;i<n;i++)
  {
    write_in(*pa);
    pa++;
  }
  WDI=1;
}

/***************************void watch_dog(void)***********************
 x5045看门狗的喂狗程序,默认的情况下1.4s 注:程序开始WDI给一次下降沿。
***********************************************************************/
void watch_dog(void)
{
  WDI=1;
  WDI=0;
  _nop_();
  _nop_();
  WDI=1;
}

/***********************bit test_wip(void)*****************************
    读状态寄存器,并返回wip位(即非易失性写操作标记位),1:内部表示忙
************************************************************************/
bit test_wip(void)
{
  WDI=0;
  _nop_();
  write_in(0x05);
  if(read_out()&0x01)  { WDI=1; _nop_(); _nop_(); return(1); }
  else                 { WDI=1; _nop_(); _nop_(); return(0); }
}

/***************************void Send_Gsm(void)***************************
串口发送数据函数,用于向GSM发送字节数据,入口和出口参数待定.
**************************************************************************/
#ifndef SEND_TO_GSM                 //Tell_Num[6]      Speed[6]
bit Send_Gsm(void)
{
  uchar k;
  uchar ret[2];
  delay_10ms(100);
  watch_dog();
  SBUF=0XD7;  while(TI==0);  TI=0;
  SBUF=0X35;  while(TI==0);  TI=0;
  for(k=0; k<6; k++)        //电话号码
  {
    SBUF=Tell_Num[k];
    while(TI==0); TI=0;
  }
  for(k=8; k<46; k++)         //中文
  {
    SBUF=gsm0[k];
    while(TI==0); TI=0;
  }
  for(k=0; k<6; k++)          //速度数字
  {
    SBUF=Speed[k];
    while(TI==0); TI=0;
  }
  SBUF=0;    while(TI==0); TI=0;
  SBUF=0X3E; while(TI==0); TI=0;

  WAT_DOG=1;
  Ex1_Time=3000;       //假设最长的发送时间为 半分钟
  COM1_TAG=1;
  watch_dog();
  while((RI==0)&&(COM1_TAG));  RI=0; //接收  D7H  FAH/FBH/BCH
  ret[0]=SBUF;
  watch_dog();
  while((RI==0)&&(COM1_TAG));  RI=0;
  ret[1]=SBUF;
  if(ret[0]!=0xD7) { WAT_DOG=0; return(0); }
  WAT_DOG=0;
  switch(ret[1])
  {
    case  0xfa:        return(1);   //发送成功
    case  0xfb:        return(0);   //发送失败
    case  0xfc:        return(0);   //模块忙
    default   :        return(0);
  }
}
#endif

/****************************void Display(void)******************************
此函数为七段数码管的显示驱动。个位,十位,为七段。百位为一段。百位:P2.7。
十位:P2.0->P2.6   个位:P0.0->P0.6  低电平驱动.
****************************************************************************/
void  Display(void)        //Send_to_89C51[3]
{
  uchar g, s, b;
  b=Send_to_89C51[3]/100;
  s=(Send_to_89C51[3]%100)/10;
  g=Send_to_89C51[3]%10;
  switch(s)           //高电平驱动
  {
    case 0:   P2=0X3F;  break;
    case 1:   P2=0X06;  break;
    case 2:   P2=0X5B;  break;
    case 3:   P2=0X4F;  break;
    case 4:   P2=0X66;  break;
    case 5:   P2=0X6D;  break;
    case 6:   P2=0X7D;  break;
    case 7:   P2=0X07;  break;
    case 8:   P2=0X7F;  break;
    case 9:   P2=0X6F;  break;
    default:    break;
  }
  if(b)  { P2_7=0; }   else{ P2_7=1; }
  switch(g)
  {
    case 0:   P0=0X3F;  break;
    case 1:   P0=0X06;  break;
    case 2:   P0=0X5B;  break;
    case 3:   P0=0X4F;  break;
    case 4:   P0=0X66;  break;
    case 5:   P0=0X6D;  break;
    case 6:   P0=0X7D;  break;
    case 7:   P0=0X07;  break;
    case 8:   P0=0X7F;  break;
    case 9:   P0=0X6F;  break;
    default:    break;
  }
}

/*****************************void Change_and_Save(void)***********************
此函数为转化和保存函数。主要完成功能:接到GSM的数据后对BCD码数据进行转化为十六
进制数据,然后保存到X5045中去。 转化结果存放在Send_to_89C51[5]数组中。为了保证
传输的可靠性,数组前3字节分别为0X3C,0XF5,0X18,Send_to_89C51[3]放速度,最后一
字节存放校验和.  传输后数据不进行反馈。
*******************************************************************************/
void Change_and_Save(void)
{
  Send_to_89C51[0] = 0X01;
  Send_to_89C51[1] = 0X17;
  Send_to_89C51[2] = 0X2c;
  if(Speed[0]||Speed[2]||Speed[4])    {  EN_SEND = FALSE; return; }
  Send_to_89C51[3] = (Speed[1]&0x0f)*100 + (Speed[3]&0x0f)*10 + (Speed[5]&0x0f);
  Send_to_89C51[4]=Send_to_89C51[0]+Send_to_89C51[1]+Send_to_89C51[2]+Send_to_89C51[3];
  if((Send_to_89C51[3]<20)||(Send_to_89C51[3]>120))  {  EN_SEND = FALSE; return; }
  in5045(0, 0, Send_to_89C51, 5);
}

/***********************************结*****束***********************************/
/*******************************************************************************/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -