从单片机基础到程序框架(连载)

2020-01-12 17:12发布

本帖最后由 吴坚鸿 于 2016-1-17 11:32 编辑

前言:
前言_pdf文件.pdf (30.44 KB, 下载次数: 729) 2016-1-17 11:30 上传 点击文件名下载附件

      大家好,我叫吴坚鸿,以前一直想写两本书,一本讲单片机入门基础,一本讲单片机程序框架。现在发现,单片机基础和程序框架并没有明显的分水岭,基础中有框架,框架中有基础,应该合二为一,读起来才会连贯舒畅。所以我决定中止当前已写到55节的《从业十年,教你单片机入门基础》连载帖,新开此连载帖。
      再提一下我2014年写的《从业将近十年,手把手教你单片机程序框架》,一方面受到很多网友的好评,另一方面也有一些热心网友提出了宝贵的意见,我今天看来,确实还有一些可待改进的地方。本来计划在2017年重写《……单片机程序框架》那个老帖,现在看来不用那么折腾了,只要把《……单片机程序框架》的内容也整合到此新帖里就可以了,这样对我也比较省事。我的时间计划是,先花4年时间写一个初稿,然后再花2年时间重写一次,最后再花1年时间整理成书,整个过程大概7年时间左右,今年是2016年,估计到2023年左右《从单片机基础到程序框架》的新书就可以出版了。
      感谢各位朋友的支持。
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
99条回答
foxpro2005
2020-01-23 18:48
本帖最后由 吴坚鸿 于 2016-3-28 09:58 编辑

第十一节:一个在单片机上练习C语言的模板程序。
第十一节_pdf文件.pdf (293.85 KB, 下载次数: 142) 2016-3-28 09:58 上传 点击文件名下载附件

第十一节可复制的模板源程序.zip (1.37 KB, 下载次数: 115) 2016-3-27 23:44 上传 点击文件名下载附件

【11.1   一套完整的模板源代码。】

       先给大家附上一套完整的模板源代码,后面章节练习C语言的模板程序就直接复制此完整的源代码,此源代码适合的单片机型号是STC89C52RC,晶振是11.0592MHz,串口波特率是9600,初学者只需修改代码里从“C语言学习区域的开始”到“C语言学习区域的结束”的区域,其它部分不要更改。可复制的源代码请到网上论坛原贴处复制或者下载,搜索本教程名字就可以找到原贴出处。一套完整的模板源代码如下:

  1. #include "REG52.H"
  2. void View(unsigned long u32ViewData);
  3. void to_BufferData(unsigned long u32Data,unsigned char *pu8Buffer,unsigned char u8Type);
  4. void SendString(unsigned char *pu8String);   

  5. /*---C语言学习区域的开始。-----------------------------------------------*/

  6. void main() //主函数
  7. {
  8.    unsigned char a; //定义一个变量a。
  9.    unsigned int  b; //定义一个变量b。
  10.    unsigned long c; //定义一个变量c。
  11.    a=100;          //给变量a赋值。
  12.    b=10000;        //给变量b赋值。
  13.    c=1000000000;   //给变量c赋值。
  14.    View(a);   //在电脑串口端查看第1个数a。
  15.    View(b);   //在电脑串口端查看第2个数b。
  16.    View(c);   //在电脑串口端查看第3个数c。
  17.    while(1)  
  18.    {
  19.    }
  20. }

  21. /*---C语言学习区域的结束。-----------------------------------------------*/

  22. void View(unsigned long u32ViewData)
  23. {
  24.     static unsigned char Su8ViewBuffer[43];
  25.             code unsigned char Cu8_0D_0A[]={0x0d,0x0a,0x00};
  26.            code unsigned char Cu8Start[]={"开始..."};
  27.     static unsigned char Su8FirstFlag=0;
  28.     static unsigned int Su16FirstDelay;
  29.     if(0==Su8FirstFlag)
  30.             {
  31.            Su8FirstFlag=1;
  32.            for(Su16FirstDelay=0;Su16FirstDelay<10000;Su16FirstDelay++);
  33.            SendString(Cu8Start);  
  34.            SendString(Cu8_0D_0A);  
  35.            SendString(Cu8_0D_0A);  
  36.    }
  37.     to_BufferData(u32ViewData,Su8ViewBuffer,1);
  38.           SendString(Su8ViewBuffer);  
  39.     to_BufferData(u32ViewData,Su8ViewBuffer,2);
  40.          SendString(Su8ViewBuffer);  
  41.     to_BufferData(u32ViewData,Su8ViewBuffer,3);
  42.          SendString(Su8ViewBuffer);  
  43.     to_BufferData(u32ViewData,Su8ViewBuffer,4);
  44.             SendString(Su8ViewBuffer);  
  45.            SendString(Cu8_0D_0A);  
  46. }
  47. void to_BufferData(unsigned long u32Data,unsigned char *pu8Buffer,unsigned char u8Type)
  48. {
  49.          code unsigned char Cu8Array1[]="第N个数";
  50.          code unsigned char Cu8Array2[]="十进制:";
  51.             code unsigned char Cu8Array3[]="十六进制:";
  52.          code unsigned char Cu8Array4[]="二进制:";
  53.     static unsigned char Su8SerialNumber=1;
  54.     static unsigned int  Su16BufferCnt;
  55.     static unsigned int  Su16TempCnt;
  56.     static unsigned int  Su16TempSet;
  57.     static unsigned long Su32Temp1;
  58.     static unsigned long Su32Temp2;
  59.     static unsigned long Su32Temp3;
  60.     static unsigned char Su8ViewFlag;
  61.     if(1==u8Type)
  62.           {
  63.         for(Su16BufferCnt=0;Su16BufferCnt<7;Su16BufferCnt++)
  64.                 {
  65.                    pu8Buffer[Su16BufferCnt]=Cu8Array1[Su16BufferCnt];
  66.               }
  67.                 pu8Buffer[2]=Su8SerialNumber+'0';
  68.                pu8Buffer[Su16BufferCnt]=0x0d;
  69.                pu8Buffer[Su16BufferCnt+1]=0x0a;
  70.                 pu8Buffer[Su16BufferCnt+2]=0;
  71.              Su8SerialNumber++;
  72.                 return;
  73.            }
  74.     else if(2==u8Type)
  75.             {
  76.                 for(Su16BufferCnt=0;Su16BufferCnt<7;Su16BufferCnt++)
  77.                 {
  78.                        pu8Buffer[Su16BufferCnt]=Cu8Array2[Su16BufferCnt];
  79.                 }
  80.                Su32Temp1=1000000000;
  81.                    Su32Temp2=10;
  82.                    Su16TempSet=10;
  83.           }
  84.     else if(3==u8Type)
  85.          {
  86.                 for(Su16BufferCnt=0;Su16BufferCnt<9;Su16BufferCnt++)
  87.                 {
  88.                        pu8Buffer[Su16BufferCnt]=Cu8Array3[Su16BufferCnt];
  89.                 }
  90.                 Su32Temp1=0x10000000;
  91.                     Su32Temp2=0x00000010;
  92.                     Su16TempSet=8;        
  93.     }
  94.     else
  95.     {
  96.                 for(Su16BufferCnt=0;Su16BufferCnt<7;Su16BufferCnt++)
  97.                 {
  98.                        pu8Buffer[Su16BufferCnt]=Cu8Array4[Su16BufferCnt];
  99.                 }
  100.                 Su32Temp1=0x80000000;
  101.                     Su32Temp2=0x00000002;
  102.                     Su16TempSet=32;        
  103.            }
  104.     Su8ViewFlag=0;
  105.     for(Su16TempCnt=0;Su16TempCnt<Su16TempSet;Su16TempCnt++)
  106.     {
  107.        Su32Temp3=u32Data/Su32Temp1%Su32Temp2;
  108.                if(Su32Temp3<10)
  109.                {
  110.                  pu8Buffer[Su16BufferCnt]=Su32Temp3+'0';
  111.                }
  112.                else
  113.                {
  114.                  pu8Buffer[Su16BufferCnt]=Su32Temp3-10+'A';
  115.                }
  116.                if(0==u32Data)
  117.                {
  118.                        Su16BufferCnt++;
  119.                        break;
  120.                }
  121.                else if(0==Su8ViewFlag)
  122.                {
  123.                    if('0'!=pu8Buffer[Su16BufferCnt])
  124.                 {
  125.                Su8ViewFlag=1;
  126.                                Su16BufferCnt++;
  127.            }
  128.                }
  129.                else
  130.                {
  131.                    Su16BufferCnt++;
  132.                }

  133.        Su32Temp1=Su32Temp1/Su32Temp2;
  134.     }
  135.     pu8Buffer[Su16BufferCnt]=0x0d;
  136.     pu8Buffer[Su16BufferCnt+1]=0x0a;
  137.     pu8Buffer[Su16BufferCnt+2]=0;
  138. }
  139. void SendString(unsigned char *pu8String)   
  140. {
  141.   static unsigned int Su16SendCnt;
  142.   static unsigned int Su16Delay;
  143.   SCON=0x50;
  144.   TMOD=0X21;
  145.   TH1=TL1=256-(11059200L/12/32/9600);  
  146.   TR1=1;
  147.   ES = 0;
  148.   TI = 0;
  149.   for(Su16SendCnt=0;Su16SendCnt<43;Su16SendCnt++)
  150.   {
  151.      if(0==pu8String[Su16SendCnt])
  152.              {
  153.                  break;
  154.              }
  155.              else
  156.              {
  157.         SBUF =pu8String[Su16SendCnt];
  158.         for(Su16Delay=0;Su16Delay<800;Su16Delay++);
  159.                    TI = 0;
  160.              }
  161.   }
  162. }

复制代码
【11.2   模板程序的使用说明。】

   

11.3.2.jpg (94.47 KB, 下载次数: 0)

下载附件

2016-3-27 23:44 上传


                                 图11.3.2

      第二步:设置串口助手软件的选项。
      先点击右上方选中“串口助手”选项切换到串口助手的窗口,接收缓冲区选择“文本模式”,串口选择匹配的COM号(跟烧录软件一致的COM号),波特率必须选择9600,勾选上“编程完成后自动打开串口”选项,最后点击“打开串口”按钮使之切换到显示“关闭串口”的文字状态,至此串口助手软件的设置完毕。接下来就是按烧录程序的流程,打开新的HEX程序文件,程序烧录完成后上位机软件会自动切换到串口助手的串口,就可以观察到View函数从单片机上发送过来的某个变量的十进制,十六进制,二进制的信息了。接收缓冲区的窗口比较小,如果收到的信息比较多,只要在上下方向拖动窗口右边的滑块就可以依次看到全部的信息。如果想让单片机重新发送数据,只要让51学习板断电重启就可以重发一次数据,当串口助手的接收区接收的信息太多影响观察时,大家可以点击“清空接收区”的按钮来清屏,然后断电重启让它再重发一次数据。在电脑的串口助手软件里观察到的数据格式大概是什么样子的呢?比如编译完本章节上述完整的模板源代码程序后,会在串口助手软件里看到a,b,c三个变量的信息如下:



  1. 开始...

  2. 第1个数
  3. 十进制:100
  4. 十六进制:64
  5. 二进制:1100100

  6. 第2个数
  7. 十进制:10000
  8. 十六进制:2710
  9. 二进制:10011100010000

  10. 第3个数
  11. 十进制:1000000000
  12. 十六进制:3B9ACA00
  13. 二进制:111011100110101100101000000000

复制代码     
         多说一句,烧录程序后,当软件自动切换到串口助手软件选项的窗口时,串口助手窗口显示单片机返回的信息,这时有可能第一行的文字“开始...”会丢失或者显示不出来,但是后面其它的关键信息不受影响,我猜测可能是串口助手软件本身的某个环节存在的小bug,跟我们没关系,我们不用深究原因,因为不会影响我们的使用。此时如果让单片机断电重启就可以看到第一行的文字“开始...”。

【11.4   如何利用现有的工程编辑编译新的源代码?】

      本教程后面有很多章节的源代码,是不是每个章节都要重新建一个工程?其实不用。我们只要用一个工程就可以编译编辑本教程所有章节的源代码。方法很简单,就是打开一个现有的工程,用快捷组合键“Ctrl+A”把原工程里面的C源代码全部选中,再按“Backspace”清空原来的代码,然后再复制本教程相关章节的代码粘贴到工程的C文档里,重新编译一次就可以得到对应的Hex格式的烧录文件。用这种方法的时候,建议大家做好每个程序代码的备份。每完成一个项目的小进度,都要及时把源代码存储到电脑硬盘里,电脑硬盘里每个项目对应一个项目文件夹,每个项目文件夹里包含很多不同版本编号的源代码文件,每个源代码文件名都有流水编号,方便识别最新版本的程序,每天下班前都要把最新版本的源代码文件上传到自己的 {MOD}里备份,在互联网时代,把源代码存到自己的 {MOD},可以随时异地存取,即使遇到电脑故障损坏也不担心数据永久丢失。

【11.5   编辑源代码的5个常用快捷键。】

      介绍一下常用的快捷键,好好利用这5个快捷键,会让你在编辑源代码时效率明显提高。
(1)选中整篇所有的内容:组合键Ctrl+A。
(2)把选中的内容复制到临时剪贴板:组合键Ctrl+C。
(3)把临时剪贴板的内容粘贴到光标开始处:组合键Ctrl+V。
(4)把选中的一行或者几行内容整体往右边移动:单键Tab。每按一次就移动几个空格,很实用。
(5)把选中的一行或者几行内容整体往左边移动:组合键Shift+Tab。每按一次就移动几个空格,很实用。

一周热门 更多>