#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
code char str1[]="AT+CSQ\r\n";
code char str2[]="AT+CSCS=\"UCS2\"\r\n";
code char str3[]="AT+CMGF=1\r\n";
code char str4[]="AT+CSMP=17,167,2,25";
code char str5[]="AT+CMGS=\"00310037003800330032003100370032003000380033\"\r\n";
code char str6[]="8B66544AFF0179EF6C348D859650";
code char str7[]="AT+CMGD=1";
void DelaySec(int sec)
{
uint i,j=0;
for(i=0;i<sec;i++)
{
for(j=0;j<65535;j++)
{
}
}
}
void uart_init(void)
{
TMOD=0x20;
SCON=0x40;
TH1=0xfd;
TL1=0xfd;
TR1=1;
ES=1;
EA=1;
}
void sendonebyte(uint c)
{
ES=0;
SBUF=c;
while(!TI);
TI=0;
ES=1;
}
void main(void)
{
uint i=0;
uart_init();
while(str1[i]!='\0')
{
sendonebyte(str1[i++]);
}
DelaySec(1);
i=0;
while(str2[i]!='\0')
{
sendonebyte(str2[i++]);
}
DelaySec(1);
i=0;
while(str3[i]!='\0')
{
sendonebyte(str3[i++]);
}
DelaySec(1);
i=0;
while(str4[i]!='\0')
{
sendonebyte(str4[i++]);
}
DelaySec(1);
i=0;
DelaySec(5);
while(str5[i]!='\0')
{
sendonebyte(str5[i++]);
}
DelaySec(1);
i=0;
while(str6[i]!='\0')
{
sendonebyte(str6[i++]);
}
DelaySec(1);
i=0;
sendonebyte(0x1A);
while(str7[i]!='\0')
{
sendonebyte(str7[i++]);
}
DelaySec(1);
i=0;
while(1);
}
void uart_isr(void) interrupt 4
{
if(RI)
{
RI=0;
}
else
TI=0;
}
上面是单独写的一个只发中文短信的,语句改成发送英文短信的后经过单片机测试可以发送,但是中文的AT指令就不行了。
#include"SIM900A.h"
#include<reg52.h>
typedef unsigned char uchar;
typedef unsigned int uint;
//注意,无论接收到信号还是发送完信号,都会进中断服务程序的
/*初始化程序(必须使用,否则无法收发),次程序将会使用定时器1*/
void SerialInti(void)//初始化程序(必须使用,否则无法收发)
{
TMOD=0x21;//定时器1操作模式2:8位自动重载定时器
TH1=0xfd;//装入初值,波特率9600
TL1=0xfd;
TR1=1;//打开定时器
SM0=0;//设置串行通讯工作模式,(10为一部发送,波特率可变,由定时器1的溢出率控制)
SM1=1;//(同上)在此模式下,定时器溢出一次就发送一个位的数据
REN=1;//串行接收允许位(要先设置sm0sm1再开串行允许)
EA=1;//开总中断
ES=1;//开串行口中断
}
void Uart1BYTE(uchar temp)
{
SBUF=temp;
while(!TI);//等待发送完成信号(TI=1)出现
TI=0;
}
//串行口连续发送char型数组,遇到终止号/0将停止
void Uart1Sends(uchar *str)
{
while(*str!='\0')
{
while(!TI);//等待发送完成信号(TI=1)出现
TI=0;
str++;
}
}
//延时函数大概是1s钟
void DelaySec(int sec)
{
uint i,j=0;
for(i=0;i<sec;i++)
{
for(j=0;j<65535;j++)
{
}
}
}
void SIM900A(void)
{
Uart1Sends("AT+CSQ\r\n");
DelaySec(1);//延时1秒
Uart1Sends("AT+CMGF=1\r\n");//文本模式
DelaySec(1);//延时1秒
Uart1Sends("AT+CSMP=17,167,2,25\r\n");//设置在工作模式
DelaySec(1);//延时1秒
Uart1Sends("AT+CSCS=\"UCS2\"");//UCS2编码字集
DelaySec(1);
Uart1Sends("AT+CMGS=\"00310037003800330032003100370032003000380033\"");//unicode电话号码
DelaySec(3);
Uart1Sends("8B66544AFF0179EF6C348D859650");//内容unicode码
DelaySec(3);//延时3秒
Uart1BYTE(0x1A);
}
这个是另一种,不清楚有没有问题的,反正编译没问题
但是调用到主程序后(以下是主程序,做的简陋的涵洞积水预警系统)
#include"ds18b20.h"
#include"csb.h"
#include"lcd.h"
#include<reg52.h>
#include"main.h"
#include"SIM900A.h"
typedef unsigned char uchar;
typedef unsigned int uint;
uint temp1[3];
uchar count = 0;
uint a1=0,Threshold1=15,Threshold2=20;
//已用端口p0.0,p0.1,p0.2,p0.3,p0.4,p0.5,p0.6,p0.7,p2.7,p2.6
//p0.0,p0.1(超声波)p0.2~p0.5(LCD)p2.0-2.3(按键)p0.6(DS18b20)
void main(void)
{
initc();//超声波初始化
init(); //lcd初始化
SerialInti();
while(1)
{
switch(P2)
{
case 0xfe:{Threshold1=Threshold1+1;display1();break;}
case 0xfd:{Threshold1=Threshold1-1;display1();break;}
case 0xfb:{Threshold2=Threshold2+1;display2();break;}
case 0xf7:{Threshold2=Threshold2-1;display2();break;}
default:break;
}
while(count < 3)
{
temp1[count]=loop();
count++;
}
a1 = (uint)(temp1[0] + temp1[1] + temp1[2]) / 3;
a1=400-a1;
count = 0;
if(a1>Threshold2)
{
SIM900A();
display();
}
else if(a1>Threshold1)
{
display();//lcd显示程序
}
else
{
display();
}
delay(3000);
}
} //0:加,1:减
void Serial_interrupt() interrupt 4//串口中断
{
if(RI)
RI=0;//接收中断信号清零,表示将继续接收
if(TI)
TI=0;
}
就会导致超声波传感器运行异常,lcd也什么都不显示了,只因为调用了SIM900A()这个函数,是不是频繁进入中断影响了超声波传感器的运行???
总之,求大佬给一个SIM900A发送中文短信的正确程序(用的是52单片机),并考虑加到我那个涵洞积水系统也可以正常发中文短信的。
以下是其他部分的.c和.h程序(怕大佬分析时有需求,特意附上,别因为感觉多就。。。),没加sim900a.c前其他程序已经在单片机跑过了的。
#include<reg52.h>
#include<intrins.h>
#include"ds18b20.h"
#include"csb.h"
#include"lcd.h"
typedef unsigned char uchar;
typedef unsigned int uint;
/*定时器0初始化*/
void initc(void)
{
TMOD=0x21;//,定时器0工作在模式一。00000001
TH0=0;
TL0=0;
ET0=1;
EA=1;
TR0 = 0;
}
void trigger(void) //单片机输入切换电平启动
{
TRIGGER=0;
TRIGGER=1;
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
TRIGGER=0;
}
uint get_distance()
{
uint time = TH0*256+TL0;
float distance;
if(read_temperature() <= 10)
{
distance = time * (330.45 * 100) / 2000000;
}
else if(read_temperature() <= 30)
{
distance = time * (342.62 * 100) / 2000000;
}
else
{
distance = time * (354.85 * 100) / 2000000;
}
TH0 = TL0 = 0;
return (uint)distance;
}
uint loop(void)
{
trigger();
while(!ECH0);
TR0=1;
while(ECH0);
TR0=0;
delay(200);//延时(大于200ms)
return get_distance();
}
/*超声波*/
#include <reg52.h>
#include "ds18b20.h"
void delay_18B20(unsigned int i)
{
for(;i>0;i--);
}
//DS18B20芯片初始化
void Init_DS18B20(void)
{
unsigned char x=0;
DQ = 1; //DQ拉高
delay_18B20(8); //稍作延时
DQ = 0; //DQ拉低
delay_18B20(80); //延时大于480us
DQ = 1; //拉高总线
delay_18B20(14);
x=DQ; //若x=0初始化成功,若x=1初始化失败
delay_18B20(20);
}
//通过单总线向DS18B20写一个字节
void WriteOneChar(unsigned char dat)
{
unsigned char i=0;
for (i=8;i>0;i--)
{
DQ=0;
DQ=dat&0x01;
if(DQ)
{
delay_18B20(1);
DQ=1;
}
else
{
delay_18B20(5);
DQ=1;
}
dat>>=1; //算术右移
}
}
//从DS18B20读取一个字节
unsigned char ReadOneChar(void) //给DQ 0,1切换信号后便会得到1位的数据反馈到DQ上
{
unsigned char i=0;
unsigned char dat=0;
for (i=8;i>0;i--)
{
DQ=0; //拉低总线
dat>>=1;//每读取移位向右移移位
DQ=1; //拉高总线
if(DQ)
dat|=0x80; //当DQ为1信号,软件将1赋给那一位
delay_18B20(4);
}
return(dat);
}
unsigned char read_temperature(void)
{
unsigned char a = 0,b = 0,temp = 0;
Init_DS18B20();
WriteOneChar(0xCC); // 跳过读序列号操作
WriteOneChar(0x44); // 启动温度转换
delay_18B20(100); //
Init_DS18B20();
WriteOneChar(0xCC); //跳过读序列号操作
WriteOneChar(0xBE); //读取温度寄存器
delay_18B20(100);
a = ReadOneChar(); //读温度低位
b = ReadOneChar(); //读温度高位
temp = b; // 以下部分和你的是一样的
temp <<= 8;
temp |= a;
if(temp < 0x8000)
{
temp = ((b * 256 + a) >> 4); // 完成的是十六进制转为10进制 ,右移4位去掉小数部分,精度12位
}
else
{
temp = -((b * 256 + a) >> 4);
}
return(temp);
}
/*温度传感器*/
#include<reg52.h>
#include<intrins.h>
#include"lcd.h"
#include"main.h"
#include"ds18b20.h"
typedef unsigned char uchar;
typedef unsigned int uint;
uchar code hanzi1[]={"当前积\xfd水深度为:"};
uchar code hanzi2[]={"谨慎通行!"};
uchar code Temp[]={"温度:"};
uchar code Threshold_A[]={"阈值A:"};
uchar code Threshold_B[]={"阈值B:"};
void delay(uint y) //单位:1ms
{ uint z;
uchar x;
for(z=0;z<y;z++)
{
for(x=0;x<120;x++);
}
}
void write_command(uchar command_data) //写指令
{
uchar i,temp,temp1,temp2;
temp=0xf8;
delay(10);
CS=1;
SCLK=0;
for(i=0;i<8;i++)
{
SID=(bit)(temp&0x80);
SCLK=0;
SCLK=1;
temp=(temp<<1);
}
temp1=command_data;
temp1=(temp1&0xf0);
for(i=0;i<8;i++)
{
SID=(bit)(temp1&0x80);
SCLK=0;
SCLK=1;
temp1=(temp1<<1);
}
temp2=command_data;
temp2=(temp2<<4);
for(i=0;i<8;i++)
{
SID=(bit)(temp2&0x80);
SCLK=0;
SCLK=1;
temp2=(temp2<<1);
}
CS=0;
}
void write_data(uchar command_data) //写数据
{
uchar temp,temp1,temp2,i;
temp=0xfa;
delay(10);
CS=1;
for(i=0;i<8;i++)
{
SID=(bit)(temp&0x80);
SCLK=0;
SCLK=1;
temp=(temp<<1);
}
temp1=command_data;
temp1=(temp1&0xf0);
for(i=0;i<8;i++)
{
SID=(bit)(temp1&0x80);
SCLK=0;
SCLK=1;
temp1=(temp1<<1);
}
temp2=command_data;
temp2=(temp2<<4);
for(i=0;i<8;i++)
{
SID=(bit)(temp2&0x80);
SCLK=0;
SCLK=1;
temp2=(temp2<<1);
}
CS=0;
}
void init(void) //初始化
{
PSB=0;
delay(100);
write_command(0x30); // 功能设置:一次送8位数据,,基本指令集。
write_command(0x04); // 点设定:显示字符/光标从左到右移位,DDRAM地址加1。
write_command(0x0c); // 显示设定:开显示,关光标,当前关闭反白闪动。
write_command(0x01); // 清DDRAM
write_command(0x02); // DDRAM地址归位
write_command(0x80); // 把显示地址设为0X80,即为第一行的首位。
}
void display(void)
{
uchar temp[2];
uchar j,i;
uint temperature=(int)read_temperature();
init();
write_command(0x80); //第一行显示
for(j=0;j<16;j++)
{
write_data(hanzi1[j]);
}
write_command(0x90);
write_data(a1/100+0x30);
write_data(a1%100/10+0x30);
write_data(a1%10+0x30);
write_data('c');
write_data('m');
if(a1>Threshold1)
{
write_command(0x88);
for(j=0;j<9;j++)
{
write_data(hanzi2[j]);
}
}
write_command(0x98);
for(i=0;i<6;i++)
{
write_data(Temp[i]); // 显示温度提示
}
temp[0]=temperature/10+0x30;
temp[1]=temperature%10+0x30;
write_command(0x98+5); // 显示温度值
for(i=0;i<2;i++)
{
write_data(temp[i]);
}
}
void display1(void)
{
uchar i;
init();
write_command(0x98);
for(i=0;i<6;i++)
{
write_data(Threshold_A[i]);
}
write_data(Threshold1/10+0x30);
write_data(Threshold1%10+0x30);
}
void display2(void)
{
uchar i;
init();
write_command(0x98);
for(i=0;i<6;i++)
{
write_data(Threshold_B[i]);
}
write_data(Threshold2/10+0x30);
write_data(Threshold2%10+0x30);
}
/*lcd12864*/