標題: 代碼研究所之單片機 [打印本頁]
作者: shaonv 時間: 2015-1-2 00:01
標題: 代碼研究所之單片機
本帖最后由 shaonv 于 2015-1-2 00:02 編輯
接觸單片機起初也要追溯到大二了,書本上學的也都是匯編或者高級匯編,對匯編我就知道兩個字無語;接觸C應該是在大一吧,純粹是為了應付考試,卻不幸掛科了,之后我不再接觸……
研究生一年級開學之初迫于老李淫威繼續C繼續單片機繼續代碼……
結合C+單片機一起來分析,學習單片機就要簡單多了:
首先要養成一個好習慣,寫函數時比如 main(),為了函數的健壯性和美觀性可這樣寫:
void main(void),第一個void表示無返回值,第二個void表示無參數。定義變量和函數名時盡量使用中文對應英文的簡寫或全稱,例如:定義一個長度的變量:unsigned char Length;若定義常量則使用以下語句:#define Length 8 此語句后面不要添加分號。
在編程的時候要注意變量值域,這是新手經常遇到的問題,多見于延時函數,例如:
void delay(void)
{
unsigned char i,j;
for(i=0;i<=30;i++)
{
for(j=0;j<=256;j++);
}
}
程序編譯無警告無錯誤,但程序運行會死掉,為什么?因為j是unsigned char 型值域為0~255,而函數中的j值超出此值,導致系統崩盤。不要小看這點錯誤,也許就是這個簡單的問題導致你的系統運行死掉。
到這里你有沒有發現每次都要寫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;
注意以上兩種方式效果是一樣的,寫法區別還要看清楚前面和后面的符號。
簡單的講述了以上基本編寫單片機程序的主意事項,下面我們來看一個簡單的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;//滅
}
}
以上便實現了簡單的使用51單片機點亮一個LED燈,當然實現流水燈的方法也是水到渠成的,程序如下:
#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();
}
}
}
以上程序便能實現簡單的流水燈,如果想要不同的花樣可在延時時間和流水燈走燈路線上更改。
為了便于程序的可移植性,一般都采用替代方式聲明,此程序中是采用P0口作為LED燈的輸出口,所以用了以下語句來增加程序的可移植性:#define LedPort P0 //為LED口
在學習單片機C編程時要重細節,粗看框架,多看書,勤編寫,對不同版本相同功能的程序分析各自的優缺點,取長補短,學習其長處。
以上便是我對入門單片機的程序編寫的一個簡單的概述,有不同意見或不同看法者,請留言探討,謝謝!
作者: shaonv 時間: 2015-1-2 00:02
接上代碼研究所之單片機(1),本次主要針對一些編寫代碼時所要注意的和單片機C編程的基礎知識。
一:數據類型·運算符·表達式
1.1 C51支持的數據類型
1.2 常量和變量
常量:#define CONST 10 變量:bit b_start //位變量 Char c_start//字符變量 其他略。
1.3 C51存儲器·寄存器定義 定義:分為片內數據存儲器·片外數據存儲器·片內程序存儲器·片外程序存儲器。 1.31 C51的數據存儲類型
例子:char data c_Var; //無符號char型變量,定義到內部存儲空間低128byte
1.32 寄存器 Sfr SBUF=0x99; //定義串行數據寄存器 Sfr16 T2=0xcc; //定義T2計時器數據存儲器
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;
作者: shaonv 時間: 2015-1-2 00:03
二:C51控制流
(1) 順序結構
(2) 選擇結構
1. If……else語句
2. If語句
3. Switch語句
Switch(判斷條件)
{
Case 常量表達式1:{語句塊1}break;
……
Default:{語句n+1}break;
}
4. If和switch嵌套
(3) 循環結構
1. While語句
2. Do while語句
Do{
代碼塊;
}while(條件);
3. For語句
三:函數
1.無參數函數定義
Void 函數名(void)//無參數,無返回值函數定義
{ }
Int 函數名(char a,char b)//帶參數,帶返回值函數定義
{ }
2.局部變量和全局變量 靜態局部變量和動態局部變量
Static int a;靜態(static不可省略) Auto int a;動態(auto可省略)
3. 內部函數和外部函數
(1)內部函數:static unsigned char Fun(int a); 內部函數只能被該源文件中的其他函數調用
(2)外部函數:extern unsigned char Fun(int a); 外部函數可以被其他源文件調用的函數
四:數組和指針
(1) 數組:
l 一維數組: 類型 數組名【size】;
l 二維數組 類型 數組名【size A】【size B】;
l 字符數組
Char ch1【】={‘j’,’a’,’c’,’k’,’x’,’u’};以字符形式賦值
Char ch1[]={“jackxu”}; 以字符串形式賦值
(2) 指針 1) 指針和指針變量 類型 *變量名 Int *ptr1;float *ptr2;char *ptr3;
2) 指針的引用 Int a=10;Int *p=&a; X=a ;直接訪問方式 X=*p;間接訪問方式
(3) 數組和指針 Int a[]={1,2,3,4,5,6,7,8,9,10},*ip; Ip=a; //*ip代表a[0],*(ip+i)代表a[ i];
二維數組與指針同上;
(4) 字符串和指針 不能用指針變量來修改字符串常量;
(5) 數組,指針和函數的關系
作者: shaonv 時間: 2015-1-2 00:04
1)數組可作為函數的參數:int sum(int a[],int num); 2指針作為函數參數:int sum(int *ip,int num); 3)返回指針的函數:char *ip(char *ip,char c);
(6) 指針數組和指向指針的指針
1)類型 *數組名【size】; Char *name【3】={“I”,“love”,“you”};定義了三個字符型指針數組并進行了初始化 3) 類型 **指針變量名 //指針變量的變量聲明 *指針變量 //獲取指針變量指向的指針 **指針變量 //獲取指針變量指向的指針內容
例子: 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); } } 程序輸出結果為:cp=0x1000; *cp=Tom; **cp=T ;Cp=0x1002 ;*cp=Jacky; **cp=J ;cp=0x1004; *cp=Andy ;**cp=A
作者: shaonv 時間: 2015-1-2 00:04
五:結構,聯合和枚舉
定義: 1) Stuct 結構名
{ 類型說明符 成員1 類型說明符 成員2 。。。。。。 類型說明符 成員n
}; 結構名 變量名1,變量名2…….;
2) Stuct 結構名 { 類型說明符 成員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)指向結構體變量的指針 Struct 結構體名 *指針變量名 Struct date *p_Date; P_Date=&ERR_TIME; (*p_Date).Year=99;P_Date->Month=8;
例子:求平均數 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); }
作者: shaonv 時間: 2015-1-2 00:05
本帖最后由 shaonv 于 2015-1-2 00:06 編輯
(2) 聯合體;定義: union 結構名 { 類型說明符 成員1 類型說明符 成員2 。。。。。。 類型說明符 成員n
}; 結構名 變量名1,變量名2…….;
2) union結構名 { 類型說明符 成員1 類型說明符 成員2 。。。。。。類型說明符 成員n }變量名1,變量名
2…….;
3) union { 類型說明符 成員1 類型說明符 成員2 。。。。。。 類型說明符 成員n }變量名1,變量名2…….;
(3) 枚舉 1)定義:Enum 枚舉名 { 枚舉值列表; };枚舉名 變量1,變量2,……;
2) Enum 枚舉名 { 枚舉值列表; } 枚舉名變量1,變量2,……;
六:程序設計技巧 中斷響應快速的一種解決方法
#define N 256 Char data[N] Static int couter=0; Void main(void) {If(flag==1){ Handledata(dat
a); //數據處理模塊 } }
Void Timer0 (void) inteerupt 1 { Data[counter]=AD_result; If(couter++>=N) {Flag=1; Counter=0; } }
總結:將中斷采集到的數據處理模塊移到主程序中操作,節約了中斷函數執行時間,使得程序能快速響應中斷并使得程序不會因處理模塊運行時間超過了中斷時間而出錯; 下一期我將會特別講述中斷及編程方法,中斷,中斷函數,中斷標志之間的關系及注意事項。
| 歡迎光臨 (http://m.raoushi.com/bbs/) |
Powered by Discuz! X3.1 |