单片机论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1920|回复: 13
打印 上一主题 下一主题
收起左侧

51单片机入门经验分享2-关于进制 typedef 头文件 main 延时函数等基础知识

  [复制链接]
跳转到指定楼层
楼主
接上篇帖子,单片机这种东西,如果是用来考试,翻翻书大概就可以了,如果是拿来开发一些小的作品,自学2个月,也不会太难,因为现在开发板也是很多的,资料也很丰富,如果你是想找工作,想独立开发产品,这个,对于一个刚毕业的人来说,就比较难了,很大的原因,是走了弯路,而且沿着弯路一直走了下去。我们希望分享一些有用的东西,实用的东西,让新手少走些弯路,如果每个坑都重踩一遍,这得浪费多少时间啊。
    言归正传,单片机是必须要亲自动手敲代码才能学会的,所以从这一章节开始,我们会分享一些例程,并详细解析,希望能给新手带来帮助,还是那句话,本人水平有限,老手轻拍,有错误请指出,有事请留言。
    一个经典的例程,点亮你的LED
我以手里的这块STC15W1K16PWM芯片为例来写例子,这块芯片至少还有一些人用来开发产品,学习了至少还有一定实用价值,如果你手里有同类型的芯片,那就更方便学习了,不管干什么,都是从简单到复杂的,比如学计算机,第一句就是“HELLO WORLD”,那么学习单片机,就是点亮你的LED了{:lol:}。先把原理图上传,单片机是软硬结合的东西,硬件为主,软件为辅,所以需要看原理图编程。
   新建一个KEIL4工程,把下面代码敲进去,就可以实现LED的闪烁了,但是还是需要解释下一下代码。

   
  1. /*******************************************************************
  2. * 文件名  LED0 500MS闪烁
  3. * 描述:        点亮LED
  4. * 2018-09-17 调试通过
  5. * 功能  入门模板
  6. * 作者:大核桃
  7. * 版本号:V1.00(2018.09.17)
  8. ********************************************************************/
  9. #include "config.h"
  10. #include "intrins.h"


  11. /*******************************************************************
  12. * 文件名 变量重新定义区域
  13. * 描述:        
  14. * 功 能
  15. * 作者:大核桃
  16. * 版本号:V1.00(2018.09.17)
  17. ********************************************************************/

  18. typedef unsigned char uint8;//无符号字符型
  19. typedef unsigned int  uint16;//无符号整型
  20. typedef unsigned long uint32;//无符号长整型


  21. /*******************************************************************
  22. * 文件名:位重新定义区域 函数前置声明
  23. * 描述:        
  24. * 功 能
  25. * 作者:大核桃
  26. * 版本号:V1.00(2018.09.17)
  27. ********************************************************************/
  28. void Delay500ms();                //@11.0592MHz
  29. void MCU_Port_Init(void);


  30. sbit LED0 = P1^0;
  31. sbit LED1 = P1^1;
  32. sbit LED2 = P1^2;
  33. sbit LED3 = P1^3;
  34. sbit LED4 = P1^4;
  35. sbit LED5 = P3^2;
  36. sbit LED6 = P0^0;
  37. sbit LED7 = P0^1;


  38. /*******************************************************************
  39. * 文件名 main函数入口
  40. * 描述:        
  41. * 功 能
  42. * 作者:大核桃
  43. * 版本号:V1.00(2018.09.17)
  44. ********************************************************************/
  45. void main(void)
  46. {
  47.         MCU_Port_Init();//端口模式初始化函数
  48.         //上电IO默认是0
  49.         LED0 = 1;//输出1
  50.         LED1 = 0;
  51.         LED2 = 0;
  52.         LED3 = 0;
  53.         LED4 = 0;
  54.         LED5 = 0;
  55.         LED6 = 0;
  56.         LED7 = 0;//

  57.         while(1)
  58.         {
  59.              P2 = 0XFE;//1111_1110;
  60.                  Delay500ms();//500ms延时 11.0592MHZ
  61.                  P2 = 0XFF;//1111_1111;
  62.                  Delay500ms();//500ms延时 11.0592MHZ
  63.         }
  64. }

  65. /*******************************************************************
  66. * 文件名:void MCU_Port_Init(void)
  67. * 描述:        MCU端口上电初始化函数
  68. * 功 能
  69. * 作者:大核桃
  70. * 版本号:V1.00(2018.09.17)
  71. ********************************************************************/
  72. void MCU_Port_Init(void)
  73. {
  74.         //第0 和1位配置推完输出模式,大电流
  75.         P0M1 = 0XFC; //        1111_1100
  76.         P0M0 = 0X03; // 0000_0011

  77.         //第01234位配置推完输出模式,大电流,567配置高阻输入,用于ADC
  78.         P1M1 = 0XE0; //1110_0000        
  79.         P1M0 = 0X1F; //0001_1111

  80.         //P2配置位准双向口
  81.         P2M1 = 0X00; //0000_0000        
  82.         P2M0 = 0X00; //0000_0000

  83.         P2 = 0XFF;//P2口初始化为1

  84.         //P5配置位准双向口
  85.         P5M1 = 0X00; //0000_0000        
  86.         P5M0 = 0X00; //0000_0000

  87.         P5 = 0XFF;//P5口初始化为1

  88.         //P3 23467推完输出
  89.         P3M1 = 0X00; //0000_0000        
  90.         P3M0 = 0XFC; //1101_1100

  91.         P3 = 0X23;  //0010_0011
  92.                
  93. }
  94. /*******************************************************************
  95. * 文件名:void Delay500ms()
  96. * 描述:        通用延时函数
  97. * 功 能
  98. * 作者:大核桃
  99. * 版本号:V1.00(2018.09.17)
  100. ********************************************************************/
  101. void Delay500ms()                //@11.0592MHz
  102. {
  103.         unsigned char i, j, k;

  104.         _nop_();
  105.         _nop_();
  106.         i = 22;
  107.         j = 3;
  108.         k = 227;
  109.         do
  110.         {
  111.                 do
  112.                 {
  113.                         while (--k);
  114.                 } while (--j);
  115.         } while (--i);
  116. }
复制代码



   头文件 #include "config.h"这个头文件是我们新建的,这里面是STC15W系列的寄存器地址定义等等,就好比学STC89C52RC那样,先包含头文件#include "reg52.h"一样,因为STC15W系列的不是标准的51,所以不能用REG52.H这个头文件,需要我们自己去新建一个,然后把官网的头文件复制过来就好了。
  typedef 的作用
typedef是用来声明新类型名的,也即是说我觉得unsigned char 太长了,记不住,或者每次都写很繁琐怎么办?另外起一个名字,typedef就是起到这个作用,而且用typedef定义过的是可以参与系统编译的,如果编译错误,那么编译器是提醒你的,如果你是用#define来定义,也可以,除非你保证自己的程序没有错误,如果出错,不小心把unsigned char写unsigned charr也是会通过的,因为#define知识简单的替换,并不参与系统编译。typedef的详细用法请参考C语言第四版326页,非常详细。
  
  关于无符号字符型的定义,无符号字符型占1个字节,取值范围在0-255之间,无符号基本整型占2个字节,取值范围是0-65535,但是在STM32上,我记得是unsigned short ,即无符号短整型,一直混用,当时搞得好混,后来看C语言,发现可以同时用,unsigned long,即无符号长整型,取值范围是0-4294967295,我们暂时就用到这3种类型的数据变量,至于更具体的请翻阅C语言第44页。
   关于函数前置声明
   函数如果在MAIN函数前面定义,是不要函数前置声明的,但是如果在MAIN后面定义,那就一定需要了,不然会报错的。
   sbit定义引脚
比如sbit LED0 = P1^0;,P1^0必须要大写而且必须要加一个分号,sbit定义是51单片机独有的,STM32就没有这个东西,直接初始化用就好了。
   main入口函数
   统一规定的,就这么个写法,第一个void指的是函数没有返回值,第二个void指的是函数没有形参调用,在STM32里面,就不是这样的,int main(void),是一个基本整型的变量作为返回值的。里面是一个while(1)的大循环,这没啥好说的。
  关于端口配置
   如果是用STC89C52的话,不需要端口配置的,除了P0是开漏输出,其他普通IO都是准双向口,直接赋值即可,但是STC89C52的IO驱动能力是有限的,LED小灯是一个耗电大户,必须要加一个三极管才可以,STC15W则不需要,IO可以配置位4种模式,准双向口,开漏输出,推挽输出,高阻输入4种模式,前2个没什么分别,推挽输出是大电流,可以直接驱动LED,最大可以达到20MA,但是根据使用经验,最好是灌入电流,也就是IO是0的时候,点亮LED,至于拉电流,IO上拉15MA可能就极限了。

程序中的寄存器定义P0M0 P0M1的配置,就是参照这个表格配置出来的,因为好多引脚还用在了别的上面,实现别的功能。请注意,P0M0和P0M1只是设定IO端口的工作类型,至于输出IO是低电平还是高电平,仍然是需要你自己决定的 ,不然达不到你要实现的效果。我们只是想点亮第一组LED的第一个灯,那么选择LED = 1;就可以了,然后在主循环中延时闪烁就好了。
   关于二进制和16进制
   我们在循环中,写P2 = 0XFE,这儿是将P2端口的最低位清零,换算成二进制也就是1111_1110,这个0就代表了P2口的最低位,也就是原理图中的DB0,如果我们不想并口操作IO,可以用sbit DB0 = P2^0;这样定义就可以将P2 = 0XFE,替换成DB = 0;P2 = 0XFF;替换DB0 = 1;就可以实现同样的效果,我们称这样的叫做可位操作,随着以后的学习深入,你会发现有很多寄存器不支持位操作,这就要想办法了。二进制怎么转换成16进制?16进制怎么转换成二进制呢?答案很简单,用计算器{:titter:},如下图WINDOWS自带的非常好用,还有就是自己算,也比较简单,0XFF 换成二级制也就是1111_1111,
16进制最大计数到F,从0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F,共计16个数,比如一个0XFE,是一个8位数,1111是高4位 ,1110看成低四位,从左到右,依次看过去的1对应的是8421,低四位也一样,也是8421,8*1+4*1+2*1+1*1 = 15,也就是16进制的F,8*1+4*1+2*1+1*0 = 14,也就是16进制的E,就是这样算,当然我觉得还是计算器最好用。{:lol:}
  
   关于delay延时函数
还记得我刚开始学的时候,就是不知道这个DELAY函数是怎么来的,在那里苦思冥想,也得不到结果。如果你是一个刚入门的新手,那么这个DELAY函数也不要去研究了,直接用STC的客户端配置好就完事了,注意选择好对应的内核就好了。这样的函数,没有参考的价值,没有研究意义。要定时精准,还是要用定时器来做。


好了,就到这里吧,未完待续。。。
   


评分

参与人数 2黑币 +25 收起 理由
wxxl + 5 很给力!
yousunny + 20 赞一个!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏2 转播转播 分享分享 分享淘帖 顶2 踩
回复

使用道具 举报

沙发
哈哈我哈哈 发表于 2018-10-13 15:19 | 只看该作者
真棒,感谢感谢!
回复

使用道具 举报

板凳
314340889 发表于 2018-10-19 11:32 | 只看该作者
建议想学单片机的人看看
回复

使用道具 举报

地板
1357966 发表于 2018-10-23 14:56 | 只看该作者
我认真的看完了没个字
回复

使用道具 举报

5#
bao321 发表于 2018-10-24 11:55 | 只看该作者
想知道最后那个延时函数生成的软件是什么
回复

使用道具 举报

6#
 楼主| dabing89 发表于 2018-10-24 13:28 | 只看该作者
bao321 发表于 2018-10-24 11:55
想知道最后那个延时函数生成的软件是什么

STC 的ISP程序下载客户端
回复

使用道具 举报

7#
51hei@119 发表于 2018-11-1 01:24 | 只看该作者
不赖 真不赖 继续跟进
回复

使用道具 举报

8#
嘿嘿. 发表于 2018-12-20 20:59 | 只看该作者
666可以可以的,感谢大佬指路
回复

使用道具 举报

9#
皮皮羊 发表于 2019-1-5 22:36 来自手机 | 只看该作者
很感兴趣,虚心学习。
回复

使用道具 举报

10#
海阔天空8 发表于 2019-1-8 10:32 | 只看该作者
我一看代码什么的就脑袋疼!我就认识看得见的东西:电阻,电容,晶体管,集成电路引脚,万用表指示数
回复

使用道具 举报

11#
2019keil 发表于 2019-1-23 15:12 | 只看该作者
虚心学习。
回复

使用道具 举报

12#
supper战 发表于 2019-2-16 22:22 来自手机 | 只看该作者
真心不错
回复

使用道具 举报

13#
Dotokeep 发表于 2019-3-17 21:34 | 只看该作者
        感谢分享我想求教一下69行     P2 = 0XFE;//1111_1110;中P2指的是。
回复

使用道具 举报

14#
dianzifashaoyou 发表于 2019-3-23 21:44 | 只看该作者
Dotokeep 发表于 2019-3-17 21:34
感谢分享我想求教一下69行     P2 = 0XFE;//1111_1110;中P2指的是。

P2口是单片机的P2.02.12.2.232.42.52.62.78个引脚
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|单片机论坛 |51黑电子论坛单片机. 联系QQ:125739409;技术交流QQ群582644647

Powered by 单片机教程网

快速回复 返回顶部 返回列表