EC03-DNC 4G模块的使用:
接线4根 -- 基于串口 -- GND VCC RX XT
支持透传 -- 支持 TCP,UDP网络协议
支持MQTT协议
支持Socket链路同时收发
波特率: 默认 115200
==============================
AT指令:
1. 进入AT模式:线接好,
然后向串口发送 +++ -- 注意不要换新行,然后再3s内重新发送其他 AT 指令(除了重启AT指令之外)2.进入AT 模式后,使用AT+CPIN 查看 SIM卡接入情况
AT+CSQ -- 查询信号强度3.接入服务器 , AT + SOCK=TCPC,116
AT+ICCID -- 查询SIM卡的CCID号(集成电路识别码)
AT+UART -- 查询串口的波特率
AT+UART=9600,NONE // 9600 -- 修改波特率, NONE,没有校验位AT+REBT -- 整个模块重启
---------------------------------
特殊 -- 先配置,重启后才运行服务器的东西
错误码:
ERR -1 无效命令格式
-2 无效命令
-3 无效操作符
-4 无效参数
-5 操作不允许
================================================
内网穿透
作用 -- 配置一个外网可以访问的服务器
前言:
基本的局域网结构:
单片机 192.168.0.112
电脑: 192.168.0.113
路由器:192.168.0.1单片机和电脑通过路由器获得相同的网段可以相互访问
================
前提:公网通信 -- 不认识 局域IP
引入:“内网IP穿透”:
概念:为局域网的设备提供一个外网可访问的地址和端口
步骤:
先通过网络调试助手 -- 架设 服务器
然后通过花生壳 生成 TCP 服务器 -- 得到一个外网IP
然后再自己创建一个TCP 客户端,发送信息过去给自己的服务器
===============================================
AT配置4G模块
配置4G模式 --让他访问服务器:
//查看当前心跳包:
AT+HEARTINFO:
// 1 ASCLL 0-- HEX
AT+HEARTINFO=1,sgNo1
//查询心跳包的频率(时间间隔):AT+HEARTM
//配置:
AT+HEARTM=3
-------------------------------
服务器的连接:
AT+SOCK=TCPC,公网IP,公网端口号115.236.153.174:50986
AT+SOCK=TCPC,115.236.153.174,50986
连上之后可以看到服务器 一直能接收到 我们发送的心跳包
//连接 上之后就是透传 -- 能相互通信了
=====================================
4G模块通过 外网 发送命令实现灯的开关 -- 和蓝牙一样简单 -- 但是需要提前做内网穿透 -- 优势是可以实现远距离传输
远程服务器发送指令控制C51点灯
#include"reg52.h"
#include<string.h>#define SIZE 12
sfr AUXR = 0x8E;
sbit D5 = P3^7;char cmd[SIZE];
void Delay1000ms() //@11.0592MHz
{
unsigned char i, j, k;
i = 43;
j = 6;
k = 203;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}void UartInit(void) //9600bps@11.0592MHz
{
AUXR=0x01; //减少定时器辐射 -- 抗干扰
SCON =0x50; //配置 串口口工作方式1,REN 使能接收
//不配 PCON -- 不设置倍数关系
//配置定时器1为 8位自动重装
TMOD &=0xF0; //高位清零
TMOD |=0x20; //00 10 -- 配置为定时器1为: 1 0 模式 -- 8位自动重装
//定义初值
TL1=0xFD;
TH1=0xFD; // 9600 波特率的初值
TR1= 1; // 定时器 -- 启动
EA =1; // 开启总中断
ES=1; // 开启串口中断
}
void sendByte(char a)
{
SBUF = a;
while(!TI);
TI=0;
}
void sendString(char *str)
{while(*str!='\0')
{
sendByte(*str);
str++;
}}
void main()
{
D5=1;//配置C51串口的 通信方式:
UartInit();
while(1){
Delay1000ms();
//往发送缓冲区 写入数据-- 就完成数据的发送
//sendString("mengxianggiegie\r\n");
}
}void uartHandler() interrupt 4
{
static i = 0;
char tmp;
if(RI) // 中断处理函数中,对于接收中断的响应
{
RI=0; //清楚接收中断标志位
tmp=SBUF;
if(tmp==':'){
i=0;
}
cmd[i++] = tmp;
if(cmd[0]==':' && cmd[1]=='o' && cmd[2]=='p'){//收到 o-pen 开灯
D5=0;
i=0;
memset(cmd,'\0',SIZE);
}
if(cmd[0]==':' && cmd[1]=='c' && cmd[2]=='l'){//收到 o-pen 开灯
D5=1;
i=0;
memset(cmd,'\0',SIZE);
}
if(i==12)
i=0;}
}
LCD -- 1602: 16字 * 2行
管脚:
需要用 16 根线:
第 1 脚: VSS 为电源地
第 2 脚: VDD 接 5V 正电源
第 3 脚: VL 为液晶显示器对比度调整端,接正电源时对比度最弱,接地时对比度最高,对比度
过高时会产生“鬼影”,使用时可以通过一个 10K 的电位器调整对比度第 4 脚:RS 为寄存器选择,高电平时选择数据寄存器、低电平时选择指令寄存器
第 5 脚:R/W 为读写信号线,高电平时进行读操作,低电平时进行写操作。当 RS 和 R/W 共
同为低电平时可以写入指令或者显示地址,当 RS 为低电平 R/W 为高电平时可以读忙信号,
当 RS 为高电平 R/W 为低电平时可以写入数据。
第 6 脚:E 端为使能端,当 E 端由高电平跳变成低电平时,液晶模块执行命令。
第 7~14 脚:D0~D7 为 8 位双向数据线。
第 15 脚:背光源正极。
第 16 脚:背光源负极
============================
配 RS = 1 接收的就是数据 配RS=0 接收指令(地址)
so 需要封装两个 函数 -- 对应RS是高电平的时候写内容,低电平的时候写地址
-------------------------------------
LCD1602 和 C51 的连线:
电源:
VSS -- GND
VDD -- 5V//对比度:
VO = GND
//控制线
RS -- P1.0
RW --P1.1
E -- P1.4//背光灯
A -- 5V
K -- GND数据:
D0 ~ D7: P0.0 ~P0.7
只需要知道两件事:
知道在哪显示 :(地址)
配RS=0 接收指令(地址)
知道显示什么:(内容)
配 RS = 1 接收的就是数据
就是ASCLL码 -- 直接输入字符即可 -- 'a'
LCD1602 初始化过程(8bit)
(1)延时 15ms
(2)写指令 38H(不检测忙信号)
(3)延时 5ms
(4)以后每次写指令,读/写数据操作均需要检测忙信号
(5)写指令 38H:显示模式设置
(6)写指令 08H:显示关闭
(7)写指令 01H:显示清屏
(8)写指令 06H:显示光标移动设置
(9)写指令 0CH:显示开及光标设置
忙标志:
RS =0 RW=1
怎么判断是否在忙呢?
数据的高位 BF 的值: 1 -- 忙 0 --不忙
报错积累 --定义了函数但是程序中没有被调用
*** WARNING L16: UNCALLED SEGMENT, IGNORED FOR OVERLAY PROCESS
要求写入地址时,最高位是bit7 -- 恒为高电平- 第一行,第五个 1000 0101 -- 0x85
case1: 通过LCD输出一个字符 'C'
#include"reg52.h"
#include "intrins.h"#define dataBuffer P0 // 定义8位数据线,P0端口
sbit RS=P1^0;
sbit RW=P1^1;
sbit EN=P1^4;
void check_busy() //
{
char tmp=0x80;
dataBuffer=0x80;
// 1000 0000 -- 0x80 只更新 bit7
while(tmp &= 0x80){//只要tmp -- 数据位的高位 1 的时候就是一直忙的状态,只有不忙的时候才跳出while循环
RS=0;
RW=1;EN=0;
_nop_();
EN=1;
_nop_();
_nop_();
tmp=dataBuffer;//读取总线上面的数
EN=0;
_nop_();
}}
void Write_Cmd_Func(char cmd)
{
check_busy(); //先检查是否繁忙
RS=0; //写内容
RW=0;EN=0;
_nop_(); // 给一个微秒
dataBuffer=cmd;
EN=1;
_nop_(); // tpw tf
EN=0;
_nop_();
}void Write_Data_Func(char dataShow)
{
check_busy();
RS=1;//写地址 -- 指令
RW=0;EN=0;
_nop_(); // 给一个微秒
dataBuffer=dataShow;
EN=1;
_nop_(); // tpw tf
EN=0;
_nop_();}
void Delay15ms() //@11.0592MHz
{
unsigned char i, j;i = 27;
j = 226;
do
{
while (--j);
} while (--i);
}
void Delay5ms() //@11.0592MHz
{
unsigned char i, j;i = 9;
j = 244;
do
{
while (--j);
} while (--i);
}
void LCD1602_INIT()
{
//LCD1602 初始化过程(8bit)
//(1)延时 15ms
Delay15ms();
//(2)写指令 38H(不检测忙信号)
Write_Cmd_Func(0x38);
//(3)延时 5ms
Delay5ms();
//(4)以后每次写指令,读/写数据操作均需要检测忙信号
//(5)写指令 38H:显示模式设置
Write_Cmd_Func(0x38);
//(6)写指令 08H:显示关闭
Write_Cmd_Func(0x08);
//(7)写指令 01H:显示清屏
Write_Cmd_Func(0x01);
//(8)写指令 06H:显示光标移动设置
Write_Cmd_Func(0x06);
//(9)写指令 0CH:显示开及光标设置
Write_Cmd_Func(0x0C);}
void main()
{char position =0x80 + 0x05;
char dataShow='C';
LCD1602_INIT();
Write_Cmd_Func(position); //选择要显示的地址
Write_Data_Func(dataShow); // 选择要发送的字符
}
//注意读写 区别:
读操作 : 先拉高 EN =1 后才去 读数据 tmp=dataBuffer;
写操作: 先 读取数据 tmp=dataBuffer; 在再拉高 EN=1
====================================
case2:通过输出一行字符串
#include"reg52.h"
#include "intrins.h"#define dataBuffer P0 // 定义8位数据线,P0端口
sbit RS=P1^0;
sbit RW=P1^1;
sbit EN=P1^4;
void check_busy() // 检查是否繁忙 -- 读时序操作
{
char tmp=0x80;
dataBuffer=0x80;
// 1000 0000 -- 0x80 只更新 bit7
while(tmp &= 0x80){//只要tmp -- 数据位的高位 1 的时候就是一直忙的状态,只有不忙的时候才跳出while循环
RS=0;
RW=1;EN=0;
_nop_();
EN=1;
_nop_();
_nop_();
tmp=dataBuffer;//读取总线上面的数
EN=0;
_nop_();
}}
void Write_Cmd_Func(char cmd) // 写入地址 -- 写时序操作
{
check_busy(); //先检查是否繁忙
RS=0; //写内容
RW=0;EN=0;
_nop_(); // 给一个微秒
dataBuffer=cmd;
_nop_(); // 数据建立时间 --tsp
EN=1;
_nop_(); // tpw tf
EN=0;
_nop_();
}void Write_Data_Func(char dataShow) //写入内容 -- 写时序操作
{
check_busy();
RS=1;//写地址 -- 指令
RW=0;EN=0;
_nop_(); // 给一个微秒
dataBuffer=dataShow;
_nop_();
EN=1;
_nop_(); // tpw tf
EN=0;
_nop_();}
void Delay15ms() //@11.0592MHz
{
unsigned char i, j;i = 27;
j = 226;
do
{
while (--j);
} while (--i);
}
void Delay5ms() //@11.0592MHz
{
unsigned char i, j;i = 9;
j = 244;
do
{
while (--j);
} while (--i);
}
void LCD1602_INIT()
{
//LCD1602 初始化过程(8bit)
//(1)延时 15ms
Delay15ms();
//(2)写指令 38H(不检测忙信号)
Write_Cmd_Func(0x38);
//(3)延时 5ms
Delay5ms();
//(4)以后每次写指令,读/写数据操作均需要检测忙信号
//(5)写指令 38H:显示模式设置
Write_Cmd_Func(0x38);
//(6)写指令 08H:显示关闭
Write_Cmd_Func(0x08);
//(7)写指令 01H:显示清屏
Write_Cmd_Func(0x01);
//(8)写指令 06H:显示光标移动设置
Write_Cmd_Func(0x06);
//(9)写指令 0CH:显示开及光标设置
Write_Cmd_Func(0x0C);}
void LCD1602_ShowLine(char line,char row,char *string)
{
switch(line){
case 1:
Write_Cmd_Func(0x80 + row); //选择开始位置
while(*string){
Write_Data_Func(*string);
string++;
}
break;case 2:
Write_Cmd_Func(0x80 + 0x40 +row); //选择开始位置
while(*string){
Write_Data_Func(*string);
string++;
}
break;
}
}
void main()
{char position =0x80 + 0x05;
char dataShow='C';
LCD1602_INIT();
LCD1602_ShowLine(1,5,"NO.1");
LCD1602_ShowLine(2,0,"mxj handsome");
}