xiao_bai_cai_555 2021-02-04 22:17 采纳率: 50%
浏览 660
已采纳

单片机与sim900a实现发送中文短信不成功的问题

#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*/


 

  • 写回答

8条回答 默认 最新

  • 歇歇 2021-02-05 11:55
    关注

    发送英文测试一下

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(7条)

报告相同问题?

悬赏问题

  • ¥15 Arcgis相交分析无法绘制一个或多个图形
  • ¥15 seatunnel-web使用SQL组件时候后台报错,无法找到表格
  • ¥15 fpga自动售货机数码管(相关搜索:数字时钟)
  • ¥15 用前端向数据库插入数据,通过debug发现数据能走到后端,但是放行之后就会提示错误
  • ¥30 3天&7天&&15天&销量如何统计同一行
  • ¥30 帮我写一段可以读取LD2450数据并计算距离的Arduino代码
  • ¥15 飞机曲面部件如机翼,壁板等具体的孔位模型
  • ¥15 vs2019中数据导出问题
  • ¥20 云服务Linux系统TCP-MSS值修改?
  • ¥20 关于#单片机#的问题:项目:使用模拟iic与ov2640通讯环境:F407问题:读取的ID号总是0xff,自己调了调发现在读从机数据时,SDA线上并未有信号变化(语言-c语言)