zoukankan      html  css  js  c++  java
  • 自己动手焊制硬件开发板

    一直有一个做机器人的梦,所以从去年起放弃了十多年的软件开发,开始进入嵌入式领域,先后在.Net Micro Framework 项目中完成了Ti DM335上的GPIOI2CUSB等驱动,方浅浅地了解了什么叫嵌入式开发。

    对非软件也非硬件出身的我,学硬件当然从单片入手最简单,如果直接从ARM开始,就像学语言直接从VBVC开始似的,刚开始可能觉得很有成就感,但是学久了,才知道浮在上面很难深下去了。

    正好开发USB驱动期间看了一本介绍USB的书,该书还附送PCB板,所以就从焊接这个电路板开始吧(记得最早焊过的相对复杂的电路板是大学金工实习时的收音机,不过和这个相比就是大巫见小巫了)。去了中发电子市场一两次,总算把该买的零件和工具置办齐,现在就要开始动手了(参见下图)。

    焊接后的成品(参见下图)

    对没有多少焊接经验的我来说,焊接过程即充满波折也充满乐趣。

    一开始我很担心,怕焊接时间过长烧坏了芯片,其实这种担心是多余的,一般的芯片还是比较耐高温的,上网查了些资料,说芯片最怕的是静电,所以焊接时一定记得带防静电手腕带。

    焊接完毕后,一上电,电源灯正常点亮,可没想到运行ISP程序竟无法下载,用示波器查看,发现主晶振没有起振(也可以用万用表量两管脚电压来判断)。仔细用万用表排查,发现两个问题,一是CPU有几个管脚虚焊,二是串口条线设置有些问题(看原理图理解有误),重新又补焊了CPU的几个管脚和调整了跳线,一上电ISP程序就可以正常下载了,编写了一个小测试程序,果然按钮、LED、蜂鸣器一切正常。

    接着测试USB芯片,但是很不妙,读出的ID号为0。又用万用表仔细排查,又是焊接问题,USB芯片一个管脚没有焊好,重新补焊,读ID正常。

    看来对我们新手来说,焊接这步很关键,宁愿焊的慢一些,也要焊接的牢一点。

    (不过下载了鼠标,U盘等程序,设备还是不能正常运转,用USB分析仪监控了一下,发现设备可以正常接收数据,但是无法向PC返回数据,出现总线超时错误。看来USB芯片还是有些问题,不过这有可能不是焊接的问题了,有可能和时序相关,等有时间再深入研究吧)。

    下面是我根据书中和网上的资料重新编写了测试程序:

    ----------------

    STC89C52.h

    ----------------

    #ifndef __STC89C52_H__

    #define __STC89C52_H__

    #include <REGX52.H>

    //--

    #define TRUE 1

    #define FALSE 0

    #define BOOL unsigned char

    #define UINT8 unsigned char

    #define UINT16 unsigned short int

    #define UINT32 unsigned long int

    #define UINT64 unsigned long long int

    #define INT8 signed char

    #define INT16 signed short int

    #define INT32 signed long int

    #define INT64 signed long long int

    //--

    #define Fclk 22118400UL   //主频

    #define BitRate 9600UL    //串口波特率

    //--

    void STC89C52_Init(void);

    //led 0-7

    #define Leds P2

    void SetLed(UINT8 led,BOOL ON);

    BOOL GetLed(UINT8 led);

    //key 0-7

    extern volatile UINT8 idata KeyPress,KeyValue;

    BOOL GetKey(UINT8 key);

    void Delay(UINT16 millisecond);

    void Sound(UINT16 millisecond);

    void Print(char * info);

    void PutHex(UINT32 x,UINT8 Num);         

    #endif

    ---------------------------

    STC89C52.c

    ---------------------------

    #include "stc89c52.h"

    void Keyboard_Init(void);

    void Uart_Init(void);

    //--  

    void STC89C52_Init(void)

    {

       P2=0xFF; //LED全灭

       EA=1;    //允许中断

       Keyboard_Init();

       Uart_Init();

    }

    //--

    void SetLed(UINT8 led,BOOL ON)

    {

             if(ON)

             {

                 P2 &= ~(0x1<<led);   

             }

             else

             {

                 P2 |= 0x1<<led;         

             }

    }

    BOOL GetLed(UINT8 led)

    {

       return ~((P2>>led) & 0x1);

    }

    //--

    volatile UINT8 idata KeyPress,KeyCurrent,KeyOld,KeyNoChangedTime;

    void Keyboard_Init(void)

    {

       P1 = 0xFF;               //键盘对应的IO设为输入状态

       KeyPress = 0;              //无按键按住

       KeyNoChangedTime = 0;    

       KeyOld=0;

       KeyCurrent=0;

       TMOD &= 0xF0;           //TMOD低四位控制定时器0

       TMOD |= 0x01;           //选择16位定时模式

       ET0 = 1;                //允许定时器0中断

       TR0 = 1;                //启动定时器0

    }

    //定时器0中断处理

    volatile UINT8 idata KeyValue=0;Flag=0,KeyX=0,KeyY=0,KeyXY=0;

    code KeyMap[]={0x44,0x81,0x41,0x21,0x11,0x82,0x42,0x22,0x12,0x84,0x24,0x14,0x88,0x48,0x28,0x18};                                    

    void Timer0_ISR(void) interrupt 1

    {

       UINT8 i;

       //定时

       TH0=(65536-Fclk/1000/12*5+15)/256;

       TL0=(65536-Fclk/1000/12*5+15)%256;

       //开始按键扫描

       KeyCurrent=~P1;

       //按键发生了变化

       if(KeyCurrent != KeyOld)

       {

           KeyNoChangedTime=0;

                KeyOld=KeyCurrent;

                return;

       }

       else

       {

               if(++KeyNoChangedTime>=1) //时间到

               {

             KeyNoChangedTime=1;

                        KeyPress=KeyOld;

               }

       }

      

       //---------------

       switch(Flag)

       {

          case 0:

                P0=0x0F;

                 Flag=1;

                       break;

          case 1:

                 KeyX=~P0 & 0x0F;   

                 if(KeyX != 0x0) Flag=2;

                 else KeyXY=0; 

                       break;

               case 2:

                 P0=0xF0;

                 Flag=3;

                       break;

               case 3:

                 KeyY=(~P0 & 0xF0)>>4;

                 if(KeyY != 0x0) Flag=4;

                       else KeyXY=0;

                       break;         

               case 4:

                  Flag=0;

                        if(KeyXY==0)

                        {

                         KeyXY= KeyY<<4 | KeyX;

               

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

                                {

                                   if(KeyXY==KeyMap[i])

                                   {

                                      KeyValue=i;

                                      break;

                                   }

                                }         

                        }

                        break;

             }                                  

    }

    BOOL GetKey(UINT8 key)

    {

       return (BOOL)(KeyPress>>key & 0x1);

    }

    void Delay(UINT16 millisecond)

    {          

       if(millisecond<10)

       {

           UINT8 ms  =(UINT8)millisecond;

                UINT8 num=200;

                while(ms--) while(num--);

       }

       else

       {

          UINT8 num=10;

          while(millisecond--)while(num--); 

       }

    }

    //--

    sfr P4 = 0xE8;

    sbit P4_0=P4^0;

    void Sound(UINT16 millisecond)

    {

         P4_0=0;  

             Delay(millisecond);

        P4_0=1;

    }

    //--

    void Uart_Init(void)

    {

       EA=0;                                //暂时关闭中断

       TMOD &=0x0F;            //TMOD低四位控制定时器1

       TMOD |=0x20;                        //自动重装模式

       SCON=0x50;              //串口工作在模式1

       TH1=256-Fclk/(BitRate*12*16);

       TL1=256-Fclk/(BitRate*12*16);

       PCON|=0x80;             //串口波特率加倍

       ES=1;                   //串行中断允许

       TR1=1;                  //启动定时器1

       REN=1;                  //允许接收

       EA=1;                   //允许中断

    }

    volatile BOOL Sending;

    void Uart_ISR(void) interrupt 4

    {

       if(RI)  //收到数据

       {

          RI=0;  //清中断

       }

       else

       {

          TI=0;

               Sending=FALSE;  //清正在发送数据

       }

    }                                                                                    

     

    void PutChar(UINT8 c)

    {

        SBUF=c;          //把字符写入发送缓冲区

             Sending=TRUE;

             while(Sending);  //等待发送完毕

    }

     

    code UINT8 HexTable[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};

    void PutHex(UINT32 x,UINT8 Num)

    {

        INT8 i;

             UINT8 Hexs[9]={'0','\0','\0','\0','\0','0','\0','\0','\0'};

     

             if(Num<1)Num=1;

             if(Num>8)Num=8;                                                                                                         

             for(i=Num-1;i>=0;i--)

             {

                Hexs[i]=HexTable[(x & 0xF)];

                x >>= 4; 

             } 

             Print(Hexs);

    }

     

    void Print(char * str)

    {

       while((*str)!='\0')

       {

          PutChar(*str);

               str++;

       }

    }

    ----------------

    main.c

    ----------------

    #include <REGX52.H>

    #include "..\common\stc89c52.h" 

    void main(void)

    {       

      UINT8 i;

      STC89C52_Init();

      //发送信息

      Print("Hello C51!\r\n");

      //蜂鸣器自检

      Sound(200);

      //LED自检

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

      {

         SetLed(i,TRUE);

              Delay(100);

              SetLed(i,FALSE);

      }  

      while(TRUE)

      {

         Leds=~KeyPress;

              

              if(KeyValue!=0xFF)

              {

                       PutHex(KeyValue,9); Print("\r\n");

                 KeyValue=0xFF;

              }

      }

    }

    其实上面的C51程序很简单,有C功底的人一看就会。不过学ARM却不这么容易了,想在ARM上编写一个最简单的“Hello world!”,就需要做很多初始化工作。做了近一年的.Net Micro Framework porting工作的我,要想实现这一步还真不容易(不过真正学好单片也不容易)。可见站在别人战车上习惯了,自己下来走两步,竟不知道如何举步了。VS2008VS2010等高级开发工具的出现,对我们来说,是福?是祸?我们不难想见。

        十年软件,十年硬件,一步一个脚印,只要努力就有希望!
  • 相关阅读:
    使用buildbot实现持续集成(转载)
    python 资料
    webdriver(python)学习笔记七——多层框架定位与智能等待
    webdriver(python)学习笔记六——操作测试对象
    webdriver(python)学习笔记五——层级定位
    webdriver(python)学习笔记四——定位一组元素
    keepalived工作原理和配置文件说明
    KeepAlived+MySQL互为主从
    利用keepalived和haproxy配置mysql的高可用负载均衡
    Linux系统安装Apache 2.4.6
  • 原文地址:https://www.cnblogs.com/yefanqiu/p/1590297.html
Copyright © 2011-2022 走看看