我爱萝丽爱萝丽 发表于 2016-9-6 17:37:51

第五课:进军!神奇的程序世界

本帖最后由 我爱萝丽爱萝丽 于 2016-9-13 01:20 编辑

几天开课后,发现一些问题,,想法也有改变。既然开课,就希望能做成一套成功的课程,几年后能够传为经典的课程,所以课程需要更加系统化。
现在已经调整第一个项目为《七色光芒》,前四课均已重新编辑!


从第五课开始,将真正开启程序世界的大门!


本课主要内容:学习程序的流程、调用等。

我爱萝丽爱萝丽 发表于 2016-9-13 02:46:16

1.1 循环控制


在上一课中我们使用STC软件自动生成了一个延时1秒的函数,如果以后需要延时2秒、延时半秒呢,要是每次都生成一个这个的函数,那将不可想象。
幸好有一个巧妙的办法:函数调用。
如果我们有一个延时1ms的函数,执行1000次不就是1秒了么,执行500次不就是半秒?多么机智的想法。



调用一个函数两次,我们可以写两行,调用三次,可以写三行,那调用1000次呢……
幸好有“while”。在我们的主函数中,所有的程序都在一个无限循环的while(1)里,其实它循环的次数是可以控制的。



知识点(15) while(?)循环
while(?){} 当?的值是“真”的,括号里的程序会一直执行;当?的值是“假”的,括号里的程序程序不再执行。
什么是真?大于0的数都是真的,1是真,1000也是真。什么是假?0就是假。
如果我们想要循环1000次,可以while(1000),循环一次,变成while(999)……到最后,变成while(0),自然循环就停止了。


知识点(16) unsigned int n; 变量定义
想要一个数从1000减到0,就先要定义这个数。
unsigned int   定义变量的关键字,意思是定义一个数,范围是0到65535。
unsigned int n;定义了n这个数。n只是一个名字,你也可以写成abc等都可以。


知识点(17) 1000次循环的程序实例
n=1000;
while(n)
{
    //被循环的程序
    n=n-1;//每循环一次n减小1
}


把前面所讲的组合起来,自己写一个函数吧!


知识点(18) 定义延时n毫秒函数实例
void delay_n_ms(unsigned int n)//括号里面有值代表有参数的函数,在调用这个函数时,可以顺便写n的大小。
{
    while(n)         //注意什么地方有分号,什么地方没分号
    {
      Delay1ms();
      n=n-1;//每循环一次n减小1
    }   
}


知识点(19) 调用带参数的函数
delay_n_ms(1000);    //在调用时,1000这个值就传递给了n


有了能随意控制延时时间的函数,就能让彩灯变化更加灵活,写一个每种色彩亮0.1秒,白色亮1秒的程序吧!
是不是绚丽多了?你还能想到别的变化组合吗?

#include<reg51.h>


sbit LED_R=P3^4;//定义红灯
sbit LED_G=P3^3;//定义绿灯
sbit LED_B=P3^2;//定义蓝灯


void Delay1ms()                //@12.000MHz
{
      unsigned char i, j;

      i = 12;
      j = 169;
      do
      {
                while (--j);
      } while (--i);
}

void delay_n_ms(unsigned int n) //自己定义的延时n毫秒函数
{
      while(n)         
      {
                Delay1ms();
                n=n-1;//每循环一次n减小1
      }   
}


main()
{
      
      while(1)
      {
                LED_R=1;
                LED_G=0;
                LED_B=0;
                delay_n_ms(100);//红色亮0.1秒
                                                                        
                LED_R=1;
                LED_G=1;
                LED_B=0;
                delay_n_ms(100);//黄色亮0.1秒
               
                LED_R=0;
                LED_G=1;
                LED_B=0;
                delay_n_ms(100);//绿色亮0.1秒
               
                LED_R=0;
                LED_G=1;
                LED_B=1;
                delay_n_ms(100);//青色亮0.1秒
               
                LED_R=0;
                LED_G=0;
                LED_B=1;
                delay_n_ms(100);//蓝色亮0.1秒
               
                LED_R=1;
                LED_G=0;
                LED_B=1;
                delay_n_ms(100);//紫色亮0.1秒
               
                LED_R=1;
                LED_G=1;
                LED_B=1;
                delay_n_ms(1000);//白色亮1.0秒
      }
      
}

我爱萝丽爱萝丽 发表于 2016-9-15 13:29:21

本帖最后由 我爱萝丽爱萝丽 于 2016-11-9 04:35 编辑

1.2 按键输入

单片机的三要素是什么?我认为是输入、处理、输出。上一节已经学了简单的处理和输出,这一节再学一下输入你就可以毕业啦 ≧▽≦

单片机最普遍的输入就是按键。

知识点(20) 按键的工作原理:
单片机引脚设置为高电平,通过按键接到地。
按键没有按下:单片机引脚还是高电平;
按键被按下:单片机引脚接地,变成低电平。程序读一下引脚电平就可以知道有没有按下。

知识点(21) 为什么通常按键接地
单片机的引脚在默认模式下,引脚内部是串联一个电阻接到正极的,当你的按键导通时,电流很小,不会有什么影响。
但是单片机的低电平是没有串联电阻的,如果你用按键连到正极,相当于将正反短路,可能会损坏引脚。


程序如何读引脚的状态?同样,要想先读引脚,也要先定义才能用,在我们焊接的电路中,一个按键接在P3.0引脚上:
sbit Key1=P3^0;定义之后,不进可以控制,还可以读。

知识点(22) if判断语句
if(?){ 1 } 如果?是真的,执行括号1里面的程序
else{ 2 } 否则就执行2里面的程序


单片机有哪些语句?循环和判断,无非就这两种,所有复杂的程序都是这两个组合起来的。
现在你已经都学了,是不是感觉单片机其实也没那么复杂?

知识点(23) =和==
等于 和 是否等于。
单片机语言中,有两种等于号,这点务必分清。
n=1000; n等于1000,是向n写入1000
n==1000; n是否等于1000?是对n进行判断。

知识点(24) 判断引脚状态的程序实例
if(Key1==0)//如果按键按下,引脚读到低电平
{
    LED_R=1;
    LED_G=0;
    LED_B=0;//亮红灯
}
else
{
    LED_R=0;
    LED_G=1;
    LED_B=0;//否则亮绿灯
}

赶快写程序试一下吧。

#include<reg51.h>


sbit LED_R=P3^4;//定义红灯
sbit LED_G=P3^3;//定义绿灯
sbit LED_B=P3^2;//定义蓝灯

sbit Key1=P3^0;//定义按键


void Delay1ms()                //@12.000MHz
{
      unsigned char i, j;

      i = 12;
      j = 169;
      do
      {
                while (--j);
      } while (--i);
}

void delay_n_ms(unsigned int n) //自己定义的延时n毫秒函数
{
      while(n)         
      {
                Delay1ms();
                n=n-1;//每循环一次n减小1
      }   
}


main()
{
      
      while(1)
      {
               
                if(Key1==0)//如果按键按下,引脚读到低电平
                {
                              LED_R=1;
                              LED_G=0;
                              LED_B=0;//亮红灯
                }
                else
                {
                              LED_R=0;
                              LED_G=1;
                              LED_B=0;//否则亮绿灯
                }
               
                delay_n_ms(100);//延时0.1秒 程序每秒检测10次按键

      }
      
}


我爱萝丽爱萝丽 发表于 2016-9-17 14:01:37

本帖最后由 我爱萝丽爱萝丽 于 2016-9-18 02:34 编辑

1.3 多种模式切换


前面学习的按键检测只能简单的切换两种状态,如果想要通过按键改变七种色彩该怎么做呢?


通常一般的单片机教材在讲按键检测时,都会教你用delay延时等待按键弹起、等待按键稳定……我不会这样给你讲。这样有什么问题吗?
我的导师在喝酒时都会大骂教材中的各种错误,“等待按键弹起?按键坏了弹不起来怎么办?程序死机??!”
而在我看来,教材中的各种错误,影响远不止这么点。很多学生学了delay检测按键,一辈子都只会用delay,容易养成错误的程序思维,走向歧途,缺乏对单片机的“时间片”的概念,日后难以写出复杂、实时性的程序。所以,我要在一开始,就把“时间片”的概念深印在你心中。


知识点(25) 单片机的运行与“时间片”
首先要知道,单片机能干什么?我们的电脑CPU实际上也可以看成是一个速度超快的单片机,它能一边挂QQ、一边看网页、一边打游戏,它是不是可以同时处理很多任务?NO,事实上,单片机同一时间,只能做一件事,CPU只是聪明的划分出了很多很小的“时间片”,一个很短的时间内,只执行QQ,另一个很短的时间内,只执行游戏,一秒钟内“时间片”切换几十次,看起来就像是同时在做多种事了。这种方式是单片机最正确的处理方式,以后在考虑程序时,先从时间片角度出发!




我们现在的任务很简单,检测按键,然后改变颜色,现在还用不到时间片这么高大上的东西,但对检测周期还要有一个概念:人类按一次按键大概需要0.3秒,我们大概每0.15秒检测一下按键就能满足需要。


知识点(26) 如何区分多种状态
我们的七色光芒有七种颜色,如果算上熄灭,至少有8种状态,怎么用程序对应8种状态呢?
你需要先定义一个数据:比如mode;如果mode等于0,代表熄灭,mode等于1,代表红色……mode不同的值就能代表不同状态。


知识点(27) unsigned char mode;
unsigned char 是定义数据的关键字,代表定义一个大小是0~255的数。255种模式,够用了吧。


知识点(28) 全局变量
我们定义的mode在整个程序中都会用到,所以需要定义在程序开头,它就叫做全局变量。
定义在程序开头的变量默认都是0。



想到怎么做了吗?我们每检测一次按键,就改变一下mode的值,指示颜色改变了,再用if判断不同的值显示不同颜色不就可以了么?
本课的主要内容就是这些了,更多精彩下一课再见
#include<reg51.h>


sbit LED_R=P3^4;//定义红灯
sbit LED_G=P3^3;//定义绿灯
sbit LED_B=P3^2;//定义蓝灯

sbit Key1=P3^0;//定义按键



unsigned char mode; //定义一个数据,指示不同状态。定义后mode的值是0


void Delay1ms()                //@12.000MHz
{
      unsigned char i, j;

      i = 12;
      j = 169;
      do
      {
                while (--j);
      } while (--i);
}

void delay_n_ms(unsigned int n) //自己定义的延时n毫秒函数
{
      while(n)         
      {
                Delay1ms();
                n=n-1;//每循环一次n减小1
      }   
}


main()
{
      
      while(1)
      {
               
                if(Key1==0)//如果按键按下,引脚读到低电平
                {
                        mode=mode+1;//每按一次按键,颜色模式改变
                        if(mode>7)
                        {
                              mode=0;   //七种颜色切换完,回到0重新开始
                        }
                }               
               
                if(mode==0)                //模式0,熄灭
                {
                              LED_R=0;
                              LED_G=0;
                              LED_B=0;
                }             //没有else可以不写
               
                if(mode==1)//模式1,红色
                {
                              LED_R=1;
                              LED_G=0;
                              LED_B=0;
                }
               
                if(mode==2)//模式2,黄色
                {
                              LED_R=1;
                              LED_G=1;
                              LED_B=0;
                }
               
                if(mode==3)//模式3,绿色
                {
                              LED_R=0;
                              LED_G=1;
                              LED_B=0;
                }
               
                if(mode==4)//模式4,青色
                {
                              LED_R=0;
                              LED_G=1;
                              LED_B=1;
                }
               
                if(mode==5)//模式5,蓝色
                {
                              LED_R=0;
                              LED_G=0;
                              LED_B=1;
                }
               
                if(mode==6)//模式6,紫色
                {
                              LED_R=1;
                              LED_G=0;
                              LED_B=1;
                }
               
                if(mode==7)//模式7,白色
                {
                              LED_R=1;
                              LED_G=1;
                              LED_B=1;
                }
               
                delay_n_ms(150);//程序每0.15秒检测一次按键

      }
      
}


Hi~ 发表于 2018-7-30 23:49:21

楼主void Delay1ms()                //@12.000MHz
{
      unsigned char i, j;

      i = 12;
      j = 169;
      do
      {
                while (--j);
      } while (--i);
}
这句代码是什么意思

yong216 发表于 2018-6-23 04:21:38

向楼主致敬,学单片机编程

bryan618 发表于 2018-6-15 06:42:40


顶一个,争取学会单片机。

老婆当家 发表于 2018-6-3 10:41:43

延伸的学习情况 都帮初学者考虑了 真的是太nice了

zxy2266 发表于 2018-5-21 16:22:11

这次系统的学习

Abu3boys 发表于 2018-2-27 23:14:31

没学过编程感觉云里雾里的。感谢楼主,细致的讲解。

木木子观 发表于 2018-2-5 17:28:54


赞赞赞一个先 。

nblaguna 发表于 2017-10-27 13:18:35

支持支持, 楼主辛苦了

jsjshs 发表于 2017-9-14 12:14:10

我爱萝丽爱萝丽 发表于 2016-9-13 02:46
1.1 循环控制




666666666666666666666

jsjshs 发表于 2017-9-14 12:13:47

我爱萝丽爱萝丽 发表于 2016-9-17 14:01
1.3 多种模式切换




6666666666666666

猪猪宠物 发表于 2016-9-6 17:46:48

我是沙发不?第一次沙发 爽啊哈哈。

精灵 发表于 2016-9-6 17:55:41

板凳站位~~

无光之月 发表于 2016-9-6 17:57:10

坐地板听课

xiao小菜鸟 发表于 2016-9-6 18:05:53

顶起来

xiao小菜鸟 发表于 2016-9-6 18:06:15

第一次这么考前

scdyzjcq 发表于 2016-9-6 18:41:25

顶一个,争取学会单片机。

飞一样的感觉 发表于 2016-9-6 18:44:13

顶一个

hmilycheng 发表于 2016-9-6 19:56:43

强烈建议楼主出套件!!!!!!!
可以有多个版本供大伙选择!!!!

郝峰 发表于 2016-9-6 20:20:53

支持萝莉老大,萝莉做东西想的就是十分周到 支持 支持强烈支持 老大下次做简易遥控器的时候 能加进去遥控或接受能检测动力电池电压 低压报警的功能吗?希望做进去并教给我们源码 谢谢

我是好人 发表于 2016-9-6 20:31:44

顶                                       

ludeku 发表于 2016-9-6 20:41:48

加油顶

372745995 发表于 2016-9-6 21:21:35


板凳站位,
板凳站位

adikesi 发表于 2016-9-6 22:17:37

哈哈,支持,期待更新

武杰杰 发表于 2016-9-7 08:44:58

学习一下,出个套装,大家买着方便

sgsd00775 发表于 2016-9-7 09:42:04

支持老大,我都保存好了,以后答应出来方便翻阅。

815023524 发表于 2016-9-7 11:23:38

好,这样更一步一步学习,

我爱萝丽爱萝丽 发表于 2016-9-7 11:29:09

hmilycheng 发表于 2016-9-6 19:56
强烈建议楼主出套件!!!!!!!
可以有多个版本供大伙选择!!!!

多个版本指什么

我爱萝丽爱萝丽 发表于 2016-9-7 11:37:55

郝峰 发表于 2016-9-6 20:20
支持萝莉老大,萝莉做东西想的就是十分周到 支持 支持强烈支持 老大下次做简易遥控器的时候 能加进去遥控或 ...

简易控是单向的,没有回传

lxd1990 发表于 2016-9-7 12:07:14

大哥想得周到
页: [1] 2 3 4 5 6 7 8
查看完整版本: 第五课:进军!神奇的程序世界