<body>
{time()}
{php}<?php
//php必须和标签在同一行
echo date('Y-m-d H:i:s');
?>{/php}
系统 我是搜索页<br>
博客网址:{$host}<br>
博客标题:{$name}<br>
博客副标题:{$subname}<br>
主题名称:{$theme}<br>
样式名称:{$style}<br>
版权说明:{$copyright}<br>
Z-BlogPHP 版本号:{$version}<br>
Z-BlogPHP 版本信息:{$zblogphp}<br>
Z-BlogPHP 链接(长):{$zblogphphtml}<br>
Z-BlogPHP 链接(短):{$zblogphpabbrhtml}<br>
网站语言:{$language}<br>
页面头部变量:{$header}<br>
页面尾部变量:{$footer}<br>
页面类型:{$type}<br>
当前页面页码:{$page}<br>
社会化评论区:{$socialcomment}<br>
cookie的路径:{$cookiespath}<br>
网站目录物理路径:{$path}<br>
<br>
<br>
module-by-name 模块的一些信息<br>
导航栏:<br>
内部ID:{$modules["navbar"].ID}<br>
模块名称:{$modules["navbar"].Name}<br>
文件名:{$modules["navbar"].FileName}<br>
模块内容:{$modules["navbar"].Content}<br>
htmlID:{$modules["navbar"].HtmlID}<br>
模块类型:{$modules["navbar"].Type}<br>
ul类型模块显示的最大列数:{$modules["navbar"].MaxLi}<br>
模块属性 system=系统模块,theme=主题模块,plugin=插件模块:{$modules["navbar"].Source}<br>
是否隐藏标题:{$modules["navbar"].IsHideTitle}<br>
<br>
{if $pagebar}
分页<br>
分页长度:{$pagebar.PageBarCount}<br>
每页显示文章数量:{$pagebar.PageCount}<br>
总页码数:{$pagebar.PageAll}<br>
当前页码:{$pagebar.PageNow}<br>
起始页码:{$pagebar.PageFirst}<br>
页尾页码:{$pagebar.PageLast}<br>
上一页ID:{$pagebar.PagePrevious}<br>
下一页ID:{$pagebar.PageNext}<br>
上一页Url:{$pagebar.prevbutton}<br>
下一页Url:{$pagebar.nextbutton}<br>
{/if}
{if $type == 'author'}
<br>
用户页? author user article.Author<br>
用户页面链接:{$author.Url}<br>
用户名:{$author.Name}<br>
用户别名:{$author.Alias}<br>
用户静态名:{$author.StaticName}<br>
用户级别:{$author.Level}<br>
用户级别名:{$author.LevelName}<br>
用户邮箱:{$author.Email}<br>
用户主页:{$author.HomePage}<br>
用户摘要:{$author.Intro}<br>
用户头像:{$author.Avatar}<br>
用户股发表文章数量:{$author.Articles}<br>
用户创建页面数:{$author.Pages}<br>
用户发表评论数:{$author.Comments}<br>
用户上传文件数:{$author.Uploads}<br>
{/if}
{if $type == 'tag'}
<br>
标签页?:<br>
标签名:{$tag.Name}<br>
标签链接:{$tag.Url}<br>
标签下文章数:{$tag.Count}<br>
{/if}
{if $type == 'category'}
<br>
分类页? category article.Category<br>
分类ID:{$category.ID}<br>
分类名称:{$category.Name}<br>
分类别名:{$category.Alias}<br>
分类链接:{$category.Url}<br>
分类文章数量:{$category.Count}<br>
分类摘要:{$category.Intro}<br>
分类序号:{$category.Order}<br>
分类层级:{$category.Level}<br>
分类的顶级ID:{$category.RootID}<br>
分类的上级ID:{$category.ParentID}<br>
分类的上一级类实例:{$category.Parent}<br>
分类所用模板:{$category.Template}<br>
分类下文章所用模板:{$category.LogTemplate}<br>
分类扩展数据:{$category}<br>
子分类实例数组:{if $category.SubCategorys == null} 子分类为空{/if}<br>
{/if}
<br>
模块 module-content<br>
导航栏:{module:navbar}<br>
日历:{module:calendar}<br>
控制面板:{module:controlpanel}<br>
网站分类:{module:catalog}<br>
搜索:{module:searchpanel}<br>
最新留言:{module:comments}<br>
文章归档:{module:archives}<br>
站点信息:{module:statistics}<br>
网站收藏:{module:favorite}<br>
友情链接:{module:link}<br>
图标汇集:{module:misc}<br>
作者列表:{module:authors}<br>
最近发表:{module:previous}<br>
标签列表:{module:tags}<br>
文章页<br> 搜索结果页 列表 分类列表页
文章ID:{$article.ID}<br>
文章标题:{$article.Title}<br>
文章别名:{$article.Alias}<br>
文章别名或标题:{$article.AliasFirst}<br>
文章链接:{$article.Url}<br>
文章是否置顶:{$article.IsTop}<br>
文章置顶类型:{$article.TopType}<br>
文章摘要:{$article.Intro}<br>
文章正文:{$article.Content}<br>
文章第一张图片:{if $article->AllImages}{$article.AllImages[0]}{/if}<br>
文章图片计数:{$article.ImageCount}<br>
文章第一张图片的缩略图:{if $article->AllImages}{$article.Thumbs(640, 360, 1, false)[0]}{/if}<br>
文章状态(数字):{$article.Status}<br>
文章状态(名):{$article.StatusName}<br>
是否禁止评论:{$article.IsLock}<br>
文章评论数:{$article.CommNums}<br>
文章浏览数:{$article.ViewNums}<br>
文章发布时间:{$article.Time("PostTime","Y-m-d H:i:s")}<br>
文章创建时间:{$article.Time("CreateTime","Y-m-d H:i:s")}<br>
文章更新时间:{$article.Time("UpdateTime","Y-m-d H:i:s")}<br>
文章分类数据:{$article.Category}<br>
文章作者数据:$article {"ID":"15","CateID":"1","AuthorID":"1","Tag":"","Status":"0","Type":"0","Alias":"","IsTop":"0","IsLock":false,"Title": Intro Content<br>
文章标签数组:<br>
第一个标签对象:{$article.FirstTag}<br>
文章标签计数:{$article.TagsCount}<br>
逗号分隔的文章标签:{$article.TagsName}<br>
文章类型:{$article.Type}<br>
文章类型:{$article.TypeName} ARTICLE 为普通文章,PAGE 为普通页面。<br>
<br>
{foreach $comments as $key => $comment}
{foreach $comment.Comments as $comment}
有子评论
{/foreach}
评论<br>
评论ID:{$comment.ID}<br>
评论楼号:{$comment.FloorID}<br>
评论层级:{$comment.Level}<br>
评论父ID:{$comment.ParentID}<br>
评论根ID:{$comment.RootID}<br>
评论所属文章/页面ID:{$comment.LogID}<br>
评论作者:{$comment.Author.Name}<br>
评论作者网址:{$comment.Author.HomePage}<br>
评论作者邮箱:{$comment.Author.Email}<br>
评论作者头像地址:{$comment.Author.Avatar}<br>
评论所属文章的链接:{$comment.Post.Url}<br>
评论所属文章的标题:{$comment.Post.Title}<br>
评论正文:{$comment.Content}<br>
评论者IP:{$comment.IP}<br>
评论者客户端信息:{$comment.Agent}<br>
评论发布时间:{$comment}<br>
{/foreach}
$backtrace = debug_backtrace();
// 移除当前函数调用的层级
echo "调用栈信息:\n";
foreach ($backtrace as $level => $call) {
$className = (isset($call['class'])) ? $call['class'] : '';
$methodName = $call['function'];
$fileName = $call['file'];
$lineNumber = $call['line'];
echo "层级 {$level}:\n";
echo " 类名:{$className}\n";
echo " 方法名:{$methodName}\n";
echo " 文件名:{$fileName}\n";
echo " 行号:{$lineNumber}\n";
echo "<br>";
}
看门狗是一种能够在程序正常执行出现异常时自动重置程序的功能
在需要长期执行的代码中代码总是不可避免的因为某些原因导致执行异常,如果不能从异常中恢复正常执行过程可能会导致项目的停止。所以为程序代码添加上看门狗功能是很有用的。
在51单片机中,头文件并没有定义这个寄存器地址,不过查看单片机手册可以发现是有这个功能的(在STM32单片机中可以直接使用),看门狗的寄存器地址是 0xe1,在代码中直接定义即可
sfr WDT_CONTR = 0xe1;
这个寄存器使用0-5位共6位可以设置
其中
第6位是看门狗是否开启位,为1打开看门狗
第5位是看门狗清零位,设置为1表示重新计数,硬件会自动将此位清零
第4位是看门狗执行环境,设置为1表示在空闲模式计数,0为在空闲模式不计数
第1-3位是看门狗的定时器预分配值,也就是看门狗重置的时长,超过这个时间没有重置看门狗的寄存器就会直接导致程序被重置
以下是12M晶振下的溢出时间
000 = 2分频 = 65.5毫秒
001 = 4分频 = 131毫秒
010 = 8分频 = 262.1毫秒
011 = 16分频 = 524.2毫秒
100 = 32分频 = 1.0485秒
101 = 64分频 = 2.0971秒
110 = 128分频 = 4.1943秒
111 = 256分频 = 8.3886秒
计算公式 = (12 X 预分频 X 32768)/12000000
所以这里设置为 0x111110 = 0x3e;
表示开启看门狗,设置为重新计数,设置为在空闲模式计数,预分频110=大概4秒溢出时间
代码如下:
#include <reg52.h>
//看门狗的寄存器地址
sfr WDT_CONTR = 0xe1;
//LED灯展示效果
#define LED P2
unsigned char P32_STATUS = 1; //外部中断1的状态
sbit K1 = P1^4;
sbit K2 = P1^5;
sbit K3 = P1^6;
sbit K4 = P1^7;
sbit K5 = P3^5;
void delay10ms(unsigned int);
void main(void){
unsigned char num = 0;
WDT_CONTR = 0x3e;
IT0 = 1;
EX0 = 1; //允许中断
IT1 = 1;
EX1 = 1; //允许中断
EA = 1; //开启总中断
//开机闪烁
P2 = 0xff;
delay10ms(100);
P2 = 0xaa;
delay10ms(100);
P2 = 0x55;
delay10ms(100);
while(1){
//如果看门狗没有起效,将在这里死循环
P2 = num;
num++;
delay10ms(10);
WDT_CONTR = 0x3e;//重置看门狗计数值,防止程序被重置
}
}
void delay10ms(unsigned int c)
{
unsigned char a,b;
for(;c>0;c--)
for(b=38;b>0;b--)
for(a=130;a>0;a--);
}
使用普通IO口来模拟串口通信,串口通信中使用两根信号线来进行发送和接收,RXD获取数据TXD发送数据,两个设备的RXD和TXD要交叉连接
然后发送频需要根据波特率来设置,比如9600的波特率在11.0592Mhz晶振的单片机中的发送延时就是104us
也就是发送1比特为需要的高电平时间,这个延时需要比较精确否则就有可能通信失败
USART串口协议如下,开始是空闲信号线高电平变为低电平且保存104us(以9600波特率为例)为开始信号,之后依次发送每一位比特的高低电平,发送是以低电平开始发送,直到发送完8字节,然后如果没有奇偶校验等的话就是结束信号,将电平保存高电平大于104us即为结束信号
接收和发送情况是一样的,接收的数据是从低字节到高字节顺序获取每一位
怎么判断接收完成?因为结束标志完毕之后如果继续发送数据,电平会被拉低,所以只需要获取到结束标志之后循环判断一定的时间(大于104us,比如取110us),如果在次判断是低电平说明数据还有需要继续接收,否则就是接收完毕。
代码比较简单,一般去读串口数据都是取延时中值的结果,(比如104us的一半时间52us,电平为低时延时52us,之后间隔104us)这样比较准确,也可以使用中断的方式来获取。
关于缓存数组,因为串口数据的发送时间间隔很短,没有多余的时间用于对数据的处理,所以一般都是先将数据放入到一个缓存中,待数据接收完毕之后再处理,否则可能会导致不能及时获取数据导致数据丢失。
代码如下,经过测试可以完成发送和接收:
#include <reg52.h>
#include <intrins.h>
sbit RXD2 = P2^2;
sbit TXD2 = P2^3;
unsigned char str[21] = "http://192.168.0.112/";
unsigned char buffer[50] = {0}; //接收缓存
int getbuffernum,putbuffernum,num;
void delay(void);
void delay2(void);
void Delay10ms(unsigned int c);
void putdata(unsigned char str);
void getdata(void);
void main(){
unsigned char i;
while(1){
getbuffernum = 0;
//读取串口数据
if(RXD2 == 0){
int maxnum = 1000;
while(maxnum--){
if(RXD2 == 0){
getdata();
maxnum = 1000;
}
};
}else{
if(buffer[0] != 0){
for(i=0;i<49;i++){
if(buffer[i] != 0){
putdata(buffer[i]);
buffer[i] = 0;
}else{
break;
}
}
getbuffernum = 0;
putdata(0x0d);
putdata(0x0a);
}
num = 0;
}
}
}
void getdata(){
unsigned int i;
unsigned char str = 0x0;
if(RXD2 == 0){//起始信号
num = 0;
delay2();
if(RXD2 == 0){
//接收数据
for(i=0;i<8;i++){
str >>= 1;
delay();
if(RXD2 == 1){
str |= 0x80;
}
}
}
delay();
buffer[getbuffernum] = str;
getbuffernum++;
}else{
num++;
}
}
void putdata(unsigned char str){
TXD2 = 0;
delay();
TXD2 = str & 0x1;
delay();
str >>= 1;
TXD2 = str & 0x1;
delay();
str >>= 1;
TXD2 = str & 0x1;
delay();
str >>= 1;
TXD2 = str & 0x1;
delay();
str >>= 1;
TXD2 = str & 0x1;
delay();
str >>= 1;
TXD2 = str & 0x1;
delay();
str >>= 1;
TXD2 = str & 0x1;
delay();
str >>= 1;
TXD2 = str & 0x1;
delay();
TXD2 = 1;
delay();
}
//104us 9600波特率是通过计算得出来的 num为7 表示 104us 误差 0.05us
void delay(){
//i=134 2400 (415us)通过 i=67 4800 (208us)通过 i=32 9600 (104us)通过
unsigned char i;
for(i=0;i<134;i++){}
}
void delay2(){
unsigned char i;
for(i=0;i<67;i++){}
}
////误差 0us
void Delay10ms(unsigned int c){
unsigned char a,b;
for(;c>0;c--){
for(b=38;b>0;b--){
for(a=130;a>0;a--){
}
}
}
}
硬件接线
DT-06 vcc接3.3v gnd接地 RXD接P2^3模拟串口的txd 三根线
AHT10 vin接3.3v gnd接地 SCL接P2^0模拟IIC的SCL口 SDA接 P2^1模拟IIC的SDA口
单片机使用STC90C52单片机
网站
局域网建立一个页面 my_home_status.php 用于显示和接收WiFi模块发送过来的数据
注意:接收过来的数据需要做处理,否则如果char字符组合成某个中文或者特殊字符的话会出现404错误
请求
首先单片机设置每10秒通过IIC协议采集一次AHT10温度传感器的数据
先将采集到的6个字节的数据做特殊处理,这里采用高低4字节加60作为12个字符发送,到达请求页面在依次处理。然后把这12个字符通过GET请求发送过去
串口发送给WiFi模块的内容格式为 "GET my_home_status.php?xxx=yyy"
再在这个页面中将接收到的内容结果处理之后保存到数据库中
完整代码如下:
#include <reg52.h>
sbit RXD2 = P2^2;
sbit TXD2 = P2^3;
sbit TXD1 = P3^1;
//iic
sbit DT06_SDA = P2^0;
sbit DT06_SCL = P2^1;
//GET /my_home_status.php?action=putdata&name=wendu&value=114
unsigned char buffer[56] = "GET /my_home_status.php?action=putdata&name=wendu&value="; //接收缓存
int getbuffernum,putbuffernum,num;
void delay1(void);
void Delay10ms(unsigned int c);
void putdata(unsigned char str);
void putdata2(unsigned char str);
//
unsigned char IIC_send(unsigned char data1);
void IIC_end_ack();
unsigned char IIC_read();
void IIC_stop();
void IIC_start();
void Delay(unsigned int a);
void main(){
unsigned char i;
long data1;
unsigned char datas[6];
unsigned char data2[6];
float temp;//临时变量
//初始化aht10
IIC_start();
IIC_send(0x70);
IIC_send(0xba);
IIC_stop();
Delay(3000);
while(1){
//初始化aht10 不知道为什么测量的温度不会变化
IIC_start();
IIC_send(0x70);
IIC_send(0xba);
IIC_stop();
Delay(3000);
//请求测量
IIC_start();
IIC_send(0x70); //0x38
IIC_send(0xac);
IIC_send(0x33);
IIC_send(0x00);
IIC_stop();
Delay(5000); //延时82ms
//获取数据
IIC_start();
Delay(1);
IIC_send(0x71);
datas[0] = IIC_read();
IIC_end_ack();
datas[1] = IIC_read();
IIC_end_ack();
datas[2] = IIC_read();
IIC_end_ack();
datas[3] = IIC_read();
IIC_end_ack();
datas[4] = IIC_read();
IIC_end_ack();
datas[5] = IIC_read();
IIC_end_ack();
IIC_stop();
data1 = (datas[3] & 0xf) * 65536 + datas[4] * 256 + datas[5];
temp = data1 / 1048576 * 200 - 50;
data1 = temp * 1;
data2[0] = datas[3];//(data1 / 10) + 48;
data2[1] = datas[4];//(data1 % 10) + 48;
for(i=0;i<56;i++){
putdata(buffer[i]);
}
putdata((datas[0]>>4) + 'A');
putdata((datas[0]&0xf) + 'A');
putdata((datas[1]>>4) + 'A');
putdata((datas[1]&0xf) + 'A');
putdata((datas[2]>>4) + 'A');
putdata((datas[2]&0xf) + 'A');
putdata((datas[3]>>4) + 'A');
putdata((datas[3]&0xf) + 'A');
putdata((datas[4]>>4) + 'A');
putdata((datas[4]&0xf) + 'A');
putdata((datas[5]>>4) + 'A');
putdata((datas[5]&0xf) + 'A');
putdata2(datas[0]);
putdata2(datas[1]);
putdata2(datas[2]);
putdata2(datas[3]);
putdata2(datas[4]);
putdata2(datas[5]);
putdata(0x0d); //DT-06 WIFI模块需要发送回车和换行
putdata(0x0a);
Delay10ms(1000);//10秒
}
}
void putdata(unsigned char str){
TXD2 = 0;
delay1();
TXD2 = str & 0x1;
delay1();
str >>= 1;
TXD2 = str & 0x1;
delay1();
str >>= 1;
TXD2 = str & 0x1;
delay1();
str >>= 1;
TXD2 = str & 0x1;
delay1();
str >>= 1;
TXD2 = str & 0x1;
delay1();
str >>= 1;
TXD2 = str & 0x1;
delay1();
str >>= 1;
TXD2 = str & 0x1;
delay1();
str >>= 1;
TXD2 = str & 0x1;
delay1();
TXD2 = 1;
delay1();
}
void putdata2(unsigned char str){
TXD1 = 0;
delay1();
TXD1 = str & 0x1;
delay1();
str >>= 1;
TXD1 = str & 0x1;
delay1();
str >>= 1;
TXD1 = str & 0x1;
delay1();
str >>= 1;
TXD1 = str & 0x1;
delay1();
str >>= 1;
TXD1 = str & 0x1;
delay1();
str >>= 1;
TXD1 = str & 0x1;
delay1();
str >>= 1;
TXD1 = str & 0x1;
delay1();
str >>= 1;
TXD1 = str & 0x1;
delay1();
TXD1 = 1;
delay1();
}
//104us 9600波特率是通过计算得出来的 num为7 表示 104us 误差 0.05us
void delay1(){
//i=134 2400 (415us)通过 i=67 4800 (208us)通过 i=32 9600 (104us)通过发送
unsigned char i;
for(i=0;i<134;i++){}
}
////误差 0us
void Delay10ms(unsigned int c){
unsigned char a,b;
for(;c>0;c--){
for(b=38;b>0;b--){
for(a=130;a>0;a--){
}
}
}
}
void usart0() interrupt 4{
if(RI){
RI = 0;
}
if(TI){
}
}
//IIC
//IIC起始信号
void IIC_start(){
DT06_SCL = 0;
Delay(1); //6.33us左右,必须大于4.7us
DT06_SDA = 1;
Delay(1);
DT06_SCL = 1;
Delay(1);
DT06_SDA = 0;
Delay(1);
DT06_SCL = 0;
}
//IIC停止信号
void IIC_stop(){
DT06_SCL = 0;
Delay(1);
DT06_SDA = 0;
Delay(1);
DT06_SCL = 1; //接收时将SCL拉高表示总线空闲
Delay(1);
DT06_SDA = 1;
}
//IIC读取数据
unsigned char IIC_read(){
unsigned char i,data1;
DT06_SDA = 1; //这里设置为1应该是为了保险起见,因为一方发送完之后 SDA 和 SCL 都是高电平的
for(i=0; i<8; i++){
Delay(1);
DT06_SCL = 1;
Delay(1);
data1 <<= 1; //低位先接收
data1 |= DT06_SDA; //低位或运算获取数据
Delay(1);
DT06_SCL = 0; //拉低等待对方设置数据吗?
Delay(1);
}
return data1;
}
//IIC确认ACK
void IIC_end_ack(){
DT06_SCL = 0;
Delay(1);
DT06_SDA = 0;
Delay(1);
DT06_SCL = 1;
Delay(1);
DT06_SCL = 0;
Delay(1);
}
//IIC发送信号
unsigned char IIC_send(unsigned char data1){
unsigned char i,num;
DT06_SCL = 0;
Delay(1);
for(i=0; i<8; i++){
//因为SCL现在时低电平,所以可以设置SDA 高位先发
DT06_SDA = data1 >> 7; //第一位 12345678 >> 7 = 00000001 ←----┒
data1 = data1 << 1; // 12345678 << 1 = 23456780 ---------┘
Delay(1);
DT06_SCL = 1;
Delay(1);
DT06_SCL = 0; //拉高再拉低
}
DT06_SDA = 1;
Delay(1);
DT06_SCL = 1; //发送完一个字节,等待从机响应 ACK
num = 0;
while(DT06_SDA){
num++;
Delay(2);
if(num > 200){//防止从机不响应死循环 1.几毫秒左右
DT06_SCL = 0;
return 2;
}
}
DT06_SCL = 0; //从机响应
Delay(1);
return 1;
}
//IIC延时函数
void Delay(unsigned int a){ //6.33us
unsigned char b;
for(;a>0;a--)
{
for(b=3;b>0;b--);
}
}
display:flex; 弹性布局,只对下一级元素有效
justify-content:flex-start; 左对齐
justify-content:flex-end; 右对齐
justify-content:flex-center; 居中对齐
justify-content:space-around; 平分空间
justify-content:space-between; 两端对齐,各个元素之间空隙相同
align-items:flex-center; 容器上下居中
align-items:flex-stretch; 容器上下居中且子元素占满容器高度,子容器不设置高度
display:grid; 网格布局,只对下一级元素有效,默认容器内的内容填满空间
grid-template-colums 定义每列宽度
grid-template-row 定义每行高度
repeat(auto-fill,30px) 重复填充,每个格子30px
grid-template-columns:1fr 2fr; 定义两列,第二列宽度是第一列的两倍
grid-template-columns:repeat(auto-fit,minmax(100px,1fr)); 元素平均分,如果宽度不够就换行
minmax() auto
grid-row-gap 行间距
grid-column-gap 列间距
grid-gap:5px; 行间距和列间距一样
grid-area:span 2 / span 1; 在该元素位置开始 占两行1列
用于 uart ttl 通信的计量模块,一般这些计量模块都是默认4800波特率的,如果我们的单片机波特率不支持这么高就需要使用串口调试助手进行修改
支持 Modbus 协议的默认都可以使用以下指令
首先默认是4800波特率
发送查询 01 03 00 04 00 01 C5 CB -> 返回 01 03 02 01 05 79 D7
发送修改 01 10 00 04 00 01 02 01 04 A7 87 -> 返回 01 10 00 04 00 01 40 08
此时已经修改波特率,在当前波特率发送已经无法接受到信息
调整到2400波特率之后
发送查询 01 03 00 04 00 01 C5 CB -> 返回 01 03 02 01 04 B8 17
说明已经修改完成
读取 8个寄存器数据
01 03 00 48 00 08 C4 1A
在线计算网站 https://www.23bei.com/tool/59.html