找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 3534|回復(fù): 5
收起左側(cè)

代碼研究所之單片機

[復(fù)制鏈接]
ID:71477 發(fā)表于 2015-1-2 00:01 | 顯示全部樓層 |閱讀模式
本帖最后由 shaonv 于 2015-1-2 00:02 編輯

接觸單片機起初也要追溯到大二了,書本上學(xué)的也都是匯編或者高級匯編,對匯編我就知道兩個字無語;接觸C應(yīng)該是在大一吧,純粹是為了應(yīng)付考試,卻不幸掛科了,之后我不再接觸……
    研究生一年級開學(xué)之初迫于老李淫威繼續(xù)C繼續(xù)單片機繼續(xù)代碼……
    結(jié)合C+單片機一起來分析,學(xué)習(xí)單片機就要簡單多了:
    首先要養(yǎng)成一個好習(xí)慣,寫函數(shù)時比如 main(),為了函數(shù)的健壯性和美觀性可這樣寫:
void main(void),第一個void表示無返回值,第二個void表示無參數(shù)。定義變量和函數(shù)名時盡量使用中文對應(yīng)英文的簡寫或全稱,例如:定義一個長度的變量:unsigned char Length;若定義常量則使用以下語句:#define  Length  8    此語句后面不要添加分號。
    在編程的時候要注意變量值域,這是新手經(jīng)常遇到的問題,多見于延時函數(shù),例如:
    void delay(void)
    {
        unsigned char i,j;
        for(i=0;i<=30;i++)
            {
              for(j=0;j<=256;j++);  
           }
    }
    程序編譯無警告無錯誤,但程序運行會死掉,為什么?因為j是unsigned char 型值域為0~255,而函數(shù)中的j值超出此值,導(dǎo)致系統(tǒng)崩盤。不要小看這點錯誤,也許就是這個簡單的問題導(dǎo)致你的系統(tǒng)運行死掉。
    到這里你有沒有發(fā)現(xiàn)每次都要寫unsigned char會很麻煩呢?所以要選擇一種替代方式,如下:
    #define unsigned char u8
    #define unsigned int  u16
    #define unsigned long u32
    在ARM一般采用以下方式:
    typedef unsigned char u8;
    typedef unsigned  int  u16;
    typedef unsigned long u32;
    注意以上兩種方式效果是一樣的,寫法區(qū)別還要看清楚前面和后面的符號。
    簡單的講述了以上基本編寫單片機程序的主意事項,下面我們來看一個簡單的LED燈程序:
    #include "reg51.h"
    #define unsigned char u8
    #define unsigned int  u16
    #define unsigned long u32
    sbit LED=P0^0;//p0.0為LED口
    void delay(void)
    {
        u8 i,j;
        for(i=0;i<=220;i++)
            {
              for(j=0;j<255;j++);  
           }
    }
    void main(void)
    {
        while(1)
        {
            LED=0;//亮
            delay(); //延時達到閃爍效果
            LED=1;//滅
        }
    }
    以上便實現(xiàn)了簡單的使用51單片機點亮一個LED燈,當(dāng)然實現(xiàn)流水燈的方法也是水到渠成的,程序如下:
    #include "reg51.h"
    #define unsigned char u8
    #define unsigned int  u16
    #define unsigned long u32
    #define  LedPort   P0        //為LED口
    u8 code table[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f,0xff};//p0.0-p.07順序亮,最后全滅
    void delay(void)
    {
        u8 i,j;
        for(i=0;i<=220;i++)
            {
              for(j=0;j<255;j++);  
           }
    }
    void main(void)
    {
        u8 num;
        while(1)
        {
           for(num=0;num<9;num++)
            {
                LedPort=table[ i];
                delay();
            } 
        }
    }
    以上程序便能實現(xiàn)簡單的流水燈,如果想要不同的花樣可在延時時間和流水燈走燈路線上更改。
    為了便于程序的可移植性,一般都采用替代方式聲明,此程序中是采用P0口作為LED燈的輸出口,所以用了以下語句來增加程序的可移植性:#define  LedPort   P0        //為LED口
    在學(xué)習(xí)單片機C編程時要重細節(jié),粗看框架,多看書,勤編寫,對不同版本相同功能的程序分析各自的優(yōu)缺點,取長補短,學(xué)習(xí)其長處。
    以上便是我對入門單片機的程序編寫的一個簡單的概述,有不同意見或不同看法者,請留言探討,謝謝!

相關(guān)帖子

回復(fù)

使用道具 舉報

ID:71477 發(fā)表于 2015-1-2 00:02 | 顯示全部樓層
接上代碼研究所之單片機(1),本次主要針對一些編寫代碼時所要注意的和單片機C編程的基礎(chǔ)知識。
一:數(shù)據(jù)類型·運算符·表達式
1.1        C51支持的數(shù)據(jù)類型
數(shù)據(jù)類型
名稱
長度
值域
基本類型
bit
1 bit
0,1
Unsigned char,char
1 byte
0~255,-128~127
Unsigned int,int
2byte
0~65525,-32768~32767
Unsigned long,long
4 byte
0~4294967295
Float
4 byte
6位數(shù)字
Double
8 byte
10位數(shù)字
構(gòu)造類型
數(shù)組
結(jié)構(gòu)體
共用體
枚舉
指針類型
2~3byte
存儲空間,最大64KB
空類型
1.2        常量和變量
常量:#define CONST 10 變量:bit  b_start //位變量 Char      c_start//字符變量 其他略。
1.3        C51存儲器·寄存器定義 定義:分為片內(nèi)數(shù)據(jù)存儲器·片外數(shù)據(jù)存儲器·片內(nèi)程序存儲器·片外程序存儲器。 1.31     C51的數(shù)據(jù)存儲類型
關(guān)鍵字
存儲器對應(yīng)關(guān)系
data
直接尋址片外數(shù)據(jù)存儲器(128byte
bdat
片內(nèi)位尋址存儲空間(16byte
idata
間接尋址片內(nèi)數(shù)據(jù)存儲空間,可以訪問RAM全部內(nèi)容
pdata
分頁尋址片外數(shù)據(jù)存儲器(256byte
Xdata
片外數(shù)據(jù)存儲器(64KB
Code
代碼存儲器(64KB
例子:char data c_Var; //無符號char型變量,定義到內(nèi)部存儲空間低128byte
1.32     寄存器 Sfr SBUF=0x99;         //定義串行數(shù)據(jù)寄存器 Sfr16    T2=0xcc;    //定義T2計時器數(shù)據(jù)存儲器
Sbit D0=P2^1;定義位變量 Sbit      CY=0xd7;使用絕對地址定義
使用sbit定義變量空間 Bdata unsigned char uc_shield_byte; Sbit     b_x= uc_shield_byte^1;           //定義首位 Sbit     b_y= uc_shield_byte^2; Sbit b_z=uc_shield_byte^3;
1.4        邏輯運算 與:    &&         或:||      非: ! 位邏輯運算 位與:& 位或|  位異或:   ^ 位取反:      ~
1.5        移位運算 左移位:<<,個位左移,補0; 右移位:>>,高位右移,補0;
回復(fù)

使用道具 舉報

ID:71477 發(fā)表于 2015-1-2 00:03 | 顯示全部樓層
二:C51控制流
1)              順序結(jié)構(gòu)
2)              選擇結(jié)構(gòu)
1.         If……else語句
2.         If語句
3.         Switch語句
Switch(判斷條件)
{
Case 常量表達式1{語句塊1}break;
……
Default{語句n+1}break;
}
4.         Ifswitch嵌套
3)              循環(huán)結(jié)構(gòu)
1.         While語句
2.         Do while語句
Do{
代碼塊;
}while(條件);
3.         For語句
三:函數(shù)
1.無參數(shù)函數(shù)定義
Void 函數(shù)名(void//無參數(shù),無返回值函數(shù)定義
{ }
Int 函數(shù)名(char a,char b//帶參數(shù),帶返回值函數(shù)定義
{ }
2.局部變量和全局變量 靜態(tài)局部變量和動態(tài)局部變量
Static      int       a;靜態(tài)(static不可省略) Auto        int         a;動態(tài)(auto可省略)
3.   內(nèi)部函數(shù)和外部函數(shù)
1)內(nèi)部函數(shù):static unsigned char  Funint a); 內(nèi)部函數(shù)只能被該源文件中的其他函數(shù)調(diào)用
2)外部函數(shù):extern unsigned char Funint a); 外部函數(shù)可以被其他源文件調(diào)用的函數(shù)

四:數(shù)組和指針
1)   數(shù)組:
l  一維數(shù)組: 類型      數(shù)組名【size;
l  二維數(shù)組 類型      數(shù)組名【size A】【size B】;
l  字符數(shù)組
Char ch1【】={‘j’,’a’,’c’,’k’,’x’,’u’};以字符形式賦值
Char ch1[]={“jackxu”};              以字符串形式賦值
2)   指針 1)         指針和指針變量  類型    *變量名 Int *ptr1;float *ptr2char *ptr3;
2)         指針的引用 Int  a=10;Int  *p=&a; X=a ;直接訪問方式 X=*p;間接訪問方式
3)   數(shù)組和指針 Int a[]={1,2,3,4,5,6,7,8,9,10}*ip; Ip=a //*ip代表a[0],*(ip+i)代表a[ i];
二維數(shù)組與指針同上;
4)   字符串和指針 不能用指針變量來修改字符串常量;
5)   數(shù)組,指針和函數(shù)的關(guān)系
回復(fù)

使用道具 舉報

ID:71477 發(fā)表于 2015-1-2 00:04 | 顯示全部樓層
1)數(shù)組可作為函數(shù)的參數(shù):int sum(int  a[],int num); 2指針作為函數(shù)參數(shù):int sum(int  *ip,int num); 3)返回指針的函數(shù):char *ip(char *ip,char c);

(6)   指針數(shù)組和指向指針的指針

1)類型 *數(shù)組名【size】; Char *name【3】={“I”,“l(fā)ove”,“you”};定義了三個字符型指針數(shù)組并進行了初始化 3)         類型  **指針變量名  //指針變量的變量聲明 *指針變量      //獲取指針變量指向的指針 **指針變量     //獲取指針變量指向的指針內(nèi)容

例子: Main() { Char *name[]={“Tom”,”Jacky”,”Andy”}; Char **cp=name; For(int i=0;i<3;i++) {  Printf(“cp=d%\n”,cp);  Printf(“*cp=s%\n”,*cp); Printf(“**cp=c%\n”,**cp); } } 程序輸出結(jié)果為:cp=0x1000; *cp=Tom; **cp=T ;Cp=0x1002 ;*cp=Jacky; **cp=J ;cp=0x1004; *cp=Andy ;**cp=A
回復(fù)

使用道具 舉報

ID:71477 發(fā)表于 2015-1-2 00:04 | 顯示全部樓層
五:結(jié)構(gòu),聯(lián)合和枚舉

定義:  1) Stuct 結(jié)構(gòu)名

{ 類型說明符 成員1   類型說明符 成員2   。。。。。。  類型說明符 成員n

}; 結(jié)構(gòu)名  變量名1,變量名2…….;

2) Stuct 結(jié)構(gòu)名 { 類型說明符 成員1 類型說明符 成員2  。。。。。。 類型說明符 成員n }變量名1,變量名2…….;

3) Stuct {類型說明符 成員1 類型說明符 成員2 。。。。。。 類型說明符 成員n }變量名1,變量名2…….;

例子: Struct date {Unsigned char      Year; Unsigned char   Month; Unsigned char   Day; Unsigned char    Hour;

}; Struct date  ERR_TIME【20】;

//初始化 ERR_TIME【0】.Year=99; ERR_TIME【0】.Month=8; ERR_TIME【0】.Day=23;

ERR_TIME【0】.Hour=22;

(1)指向結(jié)構(gòu)體變量的指針 Struct 結(jié)構(gòu)體名 *指針變量名 Struct date *p_Date; P_Date=&ERR_TIME; (*p_Date).Year=99;P_Date->Month=8;

例子:求平均數(shù) Struct member { Float Slaray; }flashman【5】={{3000},{4000},{5000},{6000},{7000}};

Float AVRage(struct member *p_Man) { Float avr,sum;Unsigned char  j;  Sum=avr=0; For(j=0;j<5;j++)  {Sum=sum+p_Man->Slaray;  If(j=4) { Avr=sum/5; } } Return avr; } Main() {  Float avr; Struct member *p; P=flashman; Menberavr=average(p); }
回復(fù)

使用道具 舉報

ID:71477 發(fā)表于 2015-1-2 00:05 | 顯示全部樓層
本帖最后由 shaonv 于 2015-1-2 00:06 編輯



(2) 聯(lián)合體;定義: union 結(jié)構(gòu)名 { 類型說明符 成員1 類型說明符 成員2  。。。。。。 類型說明符 成員n





}; 結(jié)構(gòu)名  變量名1,變量名2…….;



2) union結(jié)構(gòu)名 { 類型說明符 成員1  類型說明符 成員2  。。。。。。類型說明符 成員n }變量名1,變量名



2…….;



3) union {  類型說明符 成員1 類型說明符 成員2 。。。。。。 類型說明符 成員n }變量名1,變量名2…….;



(3) 枚舉 1)定義:Enum 枚舉名 { 枚舉值列表; };枚舉名 變量1,變量2,……;



  2) Enum 枚舉名 {  枚舉值列表; } 枚舉名變量1,變量2,……;



六:程序設(shè)計技巧 中斷響應(yīng)快速的一種解決方法



  #define N 256    Char data[N] Static int couter=0; Void main(void) {If(flag==1){ Handledata(dat



a);       //數(shù)據(jù)處理模塊 } }



Void Timer0 (void) inteerupt 1 { Data[counter]=AD_result; If(couter++>=N) {Flag=1; Counter=0; } }



總結(jié):將中斷采集到的數(shù)據(jù)處理模塊移到主程序中操作,節(jié)約了中斷函數(shù)執(zhí)行時間,使得程序能快速響應(yīng)中斷并使得程序不會因處理模塊運行時間超過了中斷時間而出錯; 下一期我將會特別講述中斷及編程方法,中斷,中斷函數(shù),中斷標志之間的關(guān)系及注意事項。
回復(fù)

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機教程網(wǎng)

快速回復(fù) 返回頂部 返回列表