自己动手焊制硬件开发板
一直有一個做機器人的夢,所以從去年起放棄了十多年的軟件開發,開始進入嵌入式領域,先后在.Net Micro Framework 項目中完成了Ti DM335上的GPIO、I2C、USB等驅動,方淺淺地了解了什么叫嵌入式開發。
對非軟件也非硬件出身的我,學硬件當然從單片入手最簡單,如果直接從ARM開始,就像學語言直接從VB,VC開始似的,剛開始可能覺得很有成就感,但是學久了,才知道浮在上面很難深下去了。
正好開發USB驅動期間看了一本介紹USB的書,該書還附送PCB板,所以就從焊接這個電路板開始吧(記得最早焊過的相對復雜的電路板是大學金工實習時的收音機,不過和這個相比就是大巫見小巫了)。去了中發電子市場一兩次,總算把該買的零件和工具置辦齊,現在就要開始動手了(參見下圖)。
焊接后的成品(參見下圖)
對沒有多少焊接經驗的我來說,焊接過程即充滿波折也充滿樂趣。
一開始我很擔心,怕焊接時間過長燒壞了芯片,其實這種擔心是多余的,一般的芯片還是比較耐高溫的,上網查了些資料,說芯片最怕的是靜電,所以焊接時一定記得帶防靜電手腕帶。
焊接完畢后,一上電,電源燈正常點亮,可沒想到運行ISP程序竟無法下載,用示波器查看,發現主晶振沒有起振(也可以用萬用表量兩管腳電壓來判斷)。仔細用萬用表排查,發現兩個問題,一是CPU有幾個管腳虛焊,二是串口條線設置有些問題(看原理圖理解有誤),重新又補焊了CPU的幾個管腳和調整了跳線,一上電ISP程序就可以正常下載了,編寫了一個小測試程序,果然按鈕、LED、蜂鳴器一切正常。
接著測試USB芯片,但是很不妙,讀出的ID號為0。又用萬用表仔細排查,又是焊接問題,USB芯片一個管腳沒有焊好,重新補焊,讀ID正常。
看來對我們新手來說,焊接這步很關鍵,寧愿焊的慢一些,也要焊接的牢一點。
(不過下載了鼠標,U盤等程序,設備還是不能正常運轉,用USB分析儀監控了一下,發現設備可以正常接收數據,但是無法向PC返回數據,出現總線超時錯誤??磥?/span>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工作的我,要想實現這一步還真不容易(不過真正學好單片也不容易)。可見站在別人戰車上習慣了,自己下來走兩步,竟不知道如何舉步了。VS2008、VS2010等高級開發工具的出現,對我們來說,是福?是禍?我們不難想見。
??? 十年軟件,十年硬件,一步一個腳印,只要努力就有希望!轉載于:https://www.cnblogs.com/yefanqiu/archive/2009/10/26/1590297.html
總結
以上是生活随笔為你收集整理的自己动手焊制硬件开发板的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: centos解压zip命令_Linux日
- 下一篇: 百度这个疯子