z-blogphp173相关变量

<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}


php调用过程中的堆栈代码段
admin 2024年09月27日 0 82 未分类

$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--);

}


51单片机模拟串口通信
admin 2024年09月27日 0 72 经验心得

使用普通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--){

}

}

}

}


教学篇-DS1302时钟芯片的设置和读取

时钟芯片使用SPI协议,使用三根线连接,分别是

RST(连接单片机P3^5),控制线

SCLK(连接单片机P3^6),时钟线

I/O(连接单片机P3^4),数据线,8位一字节

DS1302的一些说明

DS1302在时钟线的上升沿读取我们放置在IO口的数据,下降沿将数据写到IO口

DS1302必须一次读写两个字节,写读(读取数据)、写写(写入日期配置等),此模式为单字节读写模式该模式下,需要时钟线在低电平时才能修改RST(CE)为高电平

时序顺序

读:SCLK↓ RST↓ -> RST↑ -> I/O数据 -> SCLK跳变↑↓ -> SCLK↓ RST↓ I/O=0

写:和上面的一样,区别在于第一字节为地址,第二字节为值;读的话是制定读取的地址,然后返回结果

显示

DS1302数据使用BCD方式保存,高4位和低4位分别为十进制的10位和各位,LCD1602数码管显示数字可以 '0' + num 方式实现

代码如下

!code=

#include <reg52.h>

#define LCD P0

sbit RS = P2^6;

sbit RW = P2^5;

sbit LCDE = P2^7;

sbit DS1302_SCLK = P3^6;

sbit DS1302_CE = P3^5;

sbit DS1302_DISO = P3^4;

void writecom(unsigned char i);

void writedata(unsigned char i);

void Delay(unsigned int a);

unsigned char readds1302(unsigned char dat);

void writeds1302(unsigned char addr^unsigned char dat);

void main(void){

unsigned char data1^temp;

//初始化LCD1602

writecom(0x38);

writecom(0x0c);

writecom(0x06);

writecom(0x01);

writecom(0x80);

//初始化DS1302

writeds1302(0x8e^0x24);//关写保护

writeds1302(0x80^0x39);

writeds1302(0x82^0x11);

writeds1302(0x84^0x17);

writeds1302(0x86^0x30);

writeds1302(0x88^0x11);

writeds1302(0x8a^0x04);

writeds1302(0x8c^0x23);

writeds1302(0x8e^0x80);//开写保护

while(1){

writecom(0x80); //重新定位

//循环显示时间

temp = readds1302(0x81);

temp &= 0x7f; 

data1 = temp / 16;

writedata('0'+data1);

data1 = temp & 0xf;

writedata('0'+data1);

writedata('-');

temp = readds1302(0x83);

data1 = temp / 16;

writedata('0'+data1);

data1 = temp & 0xf;

writedata('0'+data1);

writedata('-');

temp = readds1302(0x85);

data1 = temp / 16;

writedata('0'+data1);

data1 = temp & 0xf;

writedata('0'+data1);

writedata('-');

writecom(0x80 + 0x40); //重新定位

temp = readds1302(0x8d);

data1 = temp / 16;

writedata('0'+data1);

data1 = temp & 0xf;

writedata('0'+data1);

writedata('-');

temp = readds1302(0x89);

data1 = temp / 16;

writedata('0'+data1);

data1 = temp & 0xf;

writedata('0'+data1);

writedata('-');

temp = readds1302(0x87);

data1 = temp / 16;

writedata('0'+data1);

data1 = temp & 0xf;

writedata('0'+data1);

writedata('-');

Delay(1000);

}

}

unsigned char readds1302(unsigned char dat){

unsigned char i^temp^data1;

DS1302_SCLK = 0;

Delay(1);

DS1302_CE = 0;

Delay(1);

DS1302_CE = 1;

Delay(1);

for(i=0;i<8;i++){

  DS1302_DISO =  dat & 0x01;

  dat >>= 1;

  DS1302_SCLK = 1;

  Delay(1);

  DS1302_SCLK = 0;

}

for(i=0;i<8;i++){

  temp = DS1302_DISO; //这里只是读取了一位^而且是先读的低位

  data1 >>= 1;

  temp <<= 7;

  data1 |= temp;

  DS1302_SCLK = 1;

  Delay(1);

  DS1302_SCLK = 0;

}

//复位需要的时间

DS1302_SCLK = 0;

Delay(1);

DS1302_CE = 0;

Delay(1);

DS1302_DISO = 0;

Delay(1);

return data1;

}

void writeds1302(unsigned char addr^unsigned char dat){

unsigned char i;

DS1302_SCLK = 0;

Delay(1);

DS1302_CE = 0;

Delay(1);

DS1302_CE = 1;

Delay(1);

for(i=0;i<8;i++){

  DS1302_DISO = addr & 0x01;

  addr >>= 1;

  DS1302_SCLK = 1;

  Delay(1);

  DS1302_SCLK = 0;

}

for(i=0;i<8;i++){

  DS1302_DISO = dat & 0x01;

  dat >>= 1;

  DS1302_SCLK = 1;

  Delay(1);

  DS1302_SCLK = 0;

}

DS1302_SCLK = 0;

Delay(1);

DS1302_CE = 0;

}

void writecom(unsigned char i){

RS = 0;

RW = 0;

LCD = i;

Delay(10);

LCDE = 1;

Delay(10);

LCDE = 0;

}

void writedata(unsigned char i){

RS = 1;

RW = 0;

LCD = i;

Delay(10); //这里需要延时时间长一点

LCDE = 1;

Delay(10);

LCDE = 0;

}

void Delay(unsigned int a){

unsigned char b;

for(;a>0;a--)

{

for(b=110;b>0;b--);

}

}

!codend=

!a=资料 https://blog.csdn.net/qq_45544223/article/details/106690978


教学篇-外部中断

这次实验的是使用单片机的外部中断0和外部中断1来进行触发从而执行不同的代码片段

设置外部中断的一般过程如下

0.STC90C52的外部中断0在管脚P3.2 外部中断1在管脚P3.3 初始电平为高电平

1.设置中断的触发方式,这里设置为下降沿(高电平转低电平触发,至少保持两个时钟周期)IT0=1 IT1=1

2.打开对应允许中断位 EX0=1 EX1=1

3.打开总中断 EA=1

4.设置对应的中断函数 void int0() interrupt 0{P32_STATUS = 0;},这里触发中断之后设置变量的值为0

最后只需要在while主循环中片段这个变量的值即可

代码如下,效果是默认数码管显示1,当触发外部中断0显示一会6之后继续显示1,触发外部中断2之后显示一会8之后继续显示1


#include <reg52.h>

#define LED P0

unsigned char P32_STATUS = 1;

unsigned char P33_STATUS = 1;

unsigned char code DIG_CODE[17] = {

0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,

0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};

void Delay10ms(unsigned int);

void intconfig();

void main(void){

intconfig();

while(1){

if(P32_STATUS == 0){

LED = DIG_CODE[6];

P32_STATUS = 1;

}else if(P33_STATUS == 0){

LED = DIG_CODE[8];

P33_STATUS = 1;

}else{

LED = DIG_CODE[1];

}

Delay10ms(100);

}

}

void intconfig(){

IT0 = 1;

EX0 = 1;  //允许中断

IT1 = 1;

EX1 = 1;  //允许中断

EA = 1;   //开启总中断

}

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 int0() interrupt 0{

  P32_STATUS = 0;

}

void int1() interrupt 2{

  P33_STATUS = 0;

}


教学篇-点亮数码管

数码管每个字段都是笔画都是和P0口的八个IO口相连的,且和其他数码管相连,所以一般情况下数码管会同时亮起,因为数码管另一端是接地的,所以IO口需要输出高电平

HC6800-MS开发板中四个数码管另一端从左到右是分别接在P1^3 - P1^0,也是需要输出高电平,这四个IO口控制数码管中的通断

#define GPIO_DIG  P0 //段选

sbit LED1 = P1^3;

sbit LED2 = P1^2;

sbit LED3 = P1^1;

sbit LED4 = P1^0;

unsigned char code DIG_CODE[17] = {

0x3f^0x06^0x5b^0x4f^0x66^0x6d^0x7d^0x07^

0x7f^0x6f^0x77^0x7c^0x39^0x5e^0x79^0x71^0x01};

//0、1、2、3、4、5、6、7、8、9、A、b、C、d、E、F、.的显示码

最后

LED1 = 1;

GPIO_DIG = DIG_CODE[m];

就可以显示第一个数码管的值了,因为默认P1口是输出高电平的,所以其它管应该设置为0低电平

for(i=0;i<10;i++);

GPIO_DIG = 0x00; //消影

以上代码是指演示一些时间后将数码管值0来关闭消除上一个显示的余光

最后代码如下,是显示4个数码管同时变化的,但是并不太行,后续再研究

!code=

#include<reg52.h>

#define GPIO_DIG  P0 //段选

sbit LED1 = P1^3;

sbit LED2 = P1^2;

sbit LED3 = P1^1;

sbit LED4 = P1^0;

char num;

unsigned char code DIG_CODE[17] = {

0x3f^0x06^0x5b^0x4f^0x66^0x6d^0x7d^0x07^

0x7f^0x6f^0x77^0x7c^0x39^0x5e^0x79^0x71^0x01};

//0、1、2、3、4、5、6、7、8、9、A、b、C、d、E、F、.的显示码

void Delay10ms(unsigned int);

void main(void){

unsigned char n^i;

TMOD = 0x01;   //定时器0 工作方式一

TH0 = (65536 - 300)/256;   //定时1ms

TL0 = (65536 - 300)%256;

TR0 = 1;   //打开定时器0中断

ET0 = 1;

EA  = 1; //开总中断

while(1){

for(n=0;n<5;n++){

num = n;

Delay10ms(100);

}

}

}

void Timer0Interrupt() interrupt 1{

unsigned char i^m;

TH0 = (65536 - 300)/256;   //定时1ms

TL0 = (65536 - 300)%256;

m = num;

LED1 = 1;

GPIO_DIG = DIG_CODE[m];

for(i=0;i<10;i++);

GPIO_DIG = 0x00; //消影

LED1 = 0;

LED2 = 1;

GPIO_DIG = DIG_CODE[m+1];

for(i=0;i<10;i++);

GPIO_DIG = 0x00;

LED2 = 0;

LED3 = 1;

GPIO_DIG = DIG_CODE[m+2];

for(i=0;i<10;i++);

GPIO_DIG = 0x00;

LED3 = 0;

LED4 = 1;

GPIO_DIG = DIG_CODE[m+3];

for(i=0;i<10;i++);

GPIO_DIG = 0x00;

LED4 = 0;

}

void Delay10ms(unsigned int c)  //误差 0us

{

    unsigned char a^b;

    for(;c>0;c--)

        for(b=38;b>0;b--)

            for(a=130;a>0;a--);

}

!codend=


教学篇-LED流水灯

#include<intrins.h> 导入位移头文件,属于内置函数,可以直接使用里面的函数,里面的功能是由编译器实现直接翻译为汇编指令,不会进行函数调用。可以方便在代码中无需内联汇编代码而可以直接使用汇编指令。

extern void _nop_ (void);

extern bit _testbit_ (bit);

extern unsigned char _cror_ (unsigned char^ unsigned char);

extern unsigned int _iror_ (unsigned int^ unsigned char);

extern unsigned long _lror_ (unsigned long^ unsigned char);

extern unsigned char _crol_ (unsigned char^ unsigned char);

extern unsigned int _irol_ (unsigned int^ unsigned char);

extern unsigned long _lrol_ (unsigned long^ unsigned char);

extern unsigned char _chkfloat_(float);

extern void _push_ (unsigned char _sfr);

extern void _pop_ (unsigned char _sfr);

主要是使用 _cror_ _crol_ 右移 和 左移函数, char 类型字符变量使用

_iror_ 整数右移 _irol_ 整数左移 _lror_ 长整型右移 _lrol_ 长整形左移

_nop_ 空操作,执行 80C51 的 NOP 指令。它是在51单片机中用的延时函数,表示执行一条没有什么意义的指令,延时一个指令周期,有的指令周期是两个或两个以上的机械周期,但是 _nop_(); 指令需要的只是一个机械周期也就是12个时钟周期(震荡周期)。如果用的是12MHZ的晶振,那么一个机械周期就是1us;也就是说:_nop_(); 延迟时间为 1us。可以较为精确得控制延迟时间。

_testbit_ 执行测试并清零 90C51 JBC 指令^测试一个位 当置位时返回1,否则返回0,如果该置位为1,则将该位复位为0,只能用于可直接寻址的位

_chkfloat_ 测试并返回源点数状态

_push_

_pop_

以下为代码

#include<reg52.h> //声明头文件

#include<intrins.h> //位移头文件

#define LED P2   //LED的8个灯

void Delay10ms(unsigned int);  //误差 0us

void main(){

unsigned char n;

LED = 0x7f;

while(1){

for(n=0;n<7;n++){

LED = _cror_(LED^1);

Delay10ms(50);

}

for(n=0;n<7;n++){

LED = _crol_(LED^1);

Delay10ms(50);

}

}

}

////误差 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--){

}

}

}

}


教学篇-点亮第一个LED灯

#include<reg52.h> 架子头文件,里面是一些定义的设备的地址

sbit 定义一个为一个位,从原理图可以看到 P20-27连接着D1-D8的负极,所以对应位设置为0即可点亮对应的LED灯,P2^7 表示选择D8 LED灯

然后就是最简单的循环代码了

代码如下

#include<reg52.h> //声明头文件

sbit LED1=P2^7;   //位操作,P2^0替换为LED1

void Delay(unsigned int a); //延时函数声明

void main() //主函数

{

while(1)

{

LED1=0; //低电平点亮

Delay(5000); //延时

LED1=1; //高电平熄灭

Delay(5000); //延时

}

}

//不准确的延时函数

void Delay(unsigned int a)

{

unsigned char b;

for(;a>0;a--)

{

for(b=110;b>0;b--);

}

}


标签1 ( 15 )
标签2 ( 12 )
标签3 ( 4 )
标签4 ( 2 )
标签5 ( 7 )
标签6 ( 5 )
标签 ( 2 )