本書主要介紹MSP430F169單片機設計方法,在適當闡述工作原理基礎上,重點介紹了硬件電路圖和軟件編程,對于重要程序,解釋編程方法并說明其工作原理。 全書共分9章:第1章為基礎篇,著重MSP430單片機工作原理以及IAR編譯軟件的應用;第2~9章為單片機設計,包括硬件系統設計和軟件編程。全書敘述簡潔、概念清晰,提供了大量應用實例,具備完整的硬件電路圖和軟件清單,涵蓋了MSP430F169單片機設計的諸多內容。 本書適合作為高等院校電氣、自動化專業高年級本科生、研究生的及高校教師教學參考書,還可以供相關工程技術人員參考。
本書內容新穎獨特,涵蓋了MSP430單片機控制系統的諸多內容。通過大量實例,介紹MSP430F169單片機的工作原理及設計方法,使讀者對基于單片機的設計有了充分的認識。對于每個課題,首先進行硬件電路設計,再進行軟件編程,注重對硬件電路設計和軟件編程中可能遇到的問題進行詳細解釋,并提供問題的解決方法,后通過實驗證明設計的正確性。對于初學者可能遇到的困惑,作者深有體會,本書通過項目實例教學,起到解疑與啟發的作用,并培養讀者分析問題和解決問題的能力。
作者簡介:陳中,鹽城工學院教師,連續多年指導學生進行畢業設計以及學科競賽,擁有豐富的教學、實踐經驗。發表過多篇關于單片機的論文,反響良好。已出版《基于STC89C52單片機的控制系統設計》《基于AVR單片機的控制系統設計》等五部著作,即將出版《基于STM32單片機的控制系統設計》一書。陳沖,鹽城工學院教師,多年從事教學科研工作。曾獲學校青年教師競賽三等獎1項,完成市級科研項目3項,獲市科技進步二等獎1項。發表過多篇具有較高學術水平的論文,先后編著《電力拖動控制系統與MATLAB仿真》《運動控制系統綜合實驗教程》等多部教材。
目錄
第1章單片機原理概述及C編程語
1.1MSP430單片機概述
1.2初步認識MSP430單片機
1.3MSP430F169單片機最小系統
1.4C語言概述
1.4.1C的變量與數據類型
1.4.2C的運算符和表達式
1.5常用的I/O相關寄存器及操作
1.6C語言的程序結構
1.6.1順序結構
1.6.2選擇結構
1.6.3循環結構
1.7C語言的函數
1.8I/O端口常用操作C語言描述及常用C語言解析
1.9把51單片機的C語言轉換成MSP430單片機的C語
1.10MSP430編譯軟件使用
1.11自制(頭)文件方法
第2章單片機輸出電路設計
2.1單片機控制系統設計概述
2.2液晶1602的顯示
2.3液晶12864的顯示
2.3.1液晶12864并行顯示
2.3.2液晶12864串行顯示
2.4LED點陣的顯示
2.5液晶12232的顯示
2.62.4in彩屏TFT的顯示
2.6.12.4in彩屏TFT簡介
2.6.2顯存地址指針與窗口工作模式
2.6.3常用寄存器設置
第3章單片機輸入電路設計
3.1鍵盤的輸入電路
3.2帶函數和小數點的計算器設計
3.3電子密碼鎖設計
3.4步進電機控制系統設計
3.5溫度檢測系統設計
3.6溫濕度傳感器的設計
3.7電子秤的設計
第4章定時器/計數器和外部中斷系統設計
4.1MSP430單片機時鐘源
4.2定時器/計數器概述
4.3TIMER_A工作模式
4.4定時器A模塊捕獲/比較工作原理
4.5定時器/計數器A與PWM
4.6外部中斷的概述
4.7秒表設計
4.8紅外遙控設計
4.9超聲波測距系統設計
4.10定時器/計數器B
4.11定時器/計數器B與PWM
4.12直流電機控制系統設計
第5章串行通信
5.1串行通信概述
5.2USART相關寄存器
5.3串行通信協議
5.4串行通信系統設計
第6章I2C接口的應用
6.1I2C通信協議概述
6.2I2C模式操作
6.3I2C寄存器說明
6.4具有斷電保護的電子密碼鎖設計
6.4.1AT24C02芯片簡介
6.4.2具有斷電保護的電子密碼鎖設計
第7章同步串行SPI接口
7.1同步串行SPI接口概述
7.2SPI相關寄存器
7.3SPI通信設計舉例——無線模塊通信設計
第8章AD與DA轉換器
8.1AD轉換器概述
8.2ADC12結構及特點
8.3ADC相關寄存器設置
8.4ADC12轉換模式
8.5AD應用實例
8.6DA轉換器概述
8.7DAC12結構與性能
8.8DAC相關寄存器設置
8.9DAC12的操作及設置和應用
第9章單片機綜合系統設計
9.1兩路溫度檢測系統設計
9.2紅外遙控直流電機調速系統設計
9.3無線通信直流電機調速系統設計
9.4用VB語言編制串行助手界面控制步進電機調速系統設計
9.5門禁控制系統設計
9.6藍牙控制系統設計
9.7彩屏和攝像頭控制系統設計
參考文獻
第3章單片機輸入電路設計
3.1鍵盤的輸入電路
鍵盤是最常用的單片機輸入電路,鍵盤主要分為兩類,一類是獨立式鍵盤,另一類是矩陣式鍵盤。如圖31(a)所示為獨立式鍵盤,雖然MSP430單片機工作電壓為3.3V,其獨立式鍵盤接的上拉電阻仍為4.8~10kΩ。其工作原理是將對應端口設置為輸入并上拉,當鍵盤未按下,相應的端口為高電平,當鍵盤被按下時,相應的端口被拉為低電平。在程序中通過查詢方法判斷端口是否為低電平,如果是,就進入此鍵盤處理程序。獨立式鍵盤適合鍵盤數量較少的場合,因為占用單片機的端口較多,比如8個鍵盤都采用獨立式鍵盤,就需要占用單片機8個端口,而矩陣式鍵盤可以節省單片機端口。矩陣式鍵盤見圖31(b)。
圖31獨立式鍵盤和矩陣式鍵盤
對于矩陣式鍵盤通常采用掃描法,設矩陣式鍵盤接單片機P1口相應的端口。其工作原理是,先將P1.7~P1.4口設置為輸出,其中有一位設置為低電平,其余設置為高電平。例如將P1.4設置為輸出且低電平,將P1.7~P1.5設置為輸出且為高電平,將P1.3~P1.0口設置為輸入并上拉,用C語言描述,即P1DIR=0xf0; P1OUT=0xef。 然后讀取P1口數值,即檢測P1電壓,如果沒有按鈕按下,則P1口電壓(數值)保持不變,其數值仍為0xef,如果在矩陣式鍵盤第4列有按鍵按下,則P1電壓(數值)發生變化,不再為0xef,假定標志為“0”的鍵盤按下,按鍵造成短路,則單片機P1.0端口就變成低電平,用C語言描述,即“if((P1IN&0x01)==0)”條件成立,把這個按鍵取鍵值為0(keyvalue=0); 如果是標志為“4”的鍵盤按下,按鍵造成短路,則單片機P1.1端口就變成低電平; 即“if((P1IN&0x02)==0)”條件成立,把這個按鍵取鍵值為4(keyvalue=4); 同理可以確定標志為“8”或“12”的鍵盤。然后再將P1.5設置為輸出且低電平,P1.7、P1.6、P1.4設置為輸出且高電平,將P1.3~P1.0口設置為輸入并上拉,用同樣的方法就能確定第3列鍵盤哪個鍵盤按下。同理就可以確定第2列、第1列哪個鍵盤被按下。對于矩陣式鍵盤,一般情況下,用9個鍵盤代表0~9的數值,稱為數值鍵,而大于9的數值鍵盤可以代表其他功能,稱為功能鍵。對于鍵盤操作還有一個重要問題,即鍵抖動現象,簡單說來,雖然只按一下按鍵然后松開,但由于單片機運行程序速度很快,它能多次運行鍵盤程序,往往會認為按了多次鍵盤。對于消除鍵盤抖動,有硬件消抖和軟件消抖,最常用的是軟件消抖,有多種方法。其中一種方法是在程序中檢測到按鍵按下后,延遲一段時間,在按鍵處理程序結束后,再延時一段時間,實踐表明能夠很好地解決鍵盤抖動問題。
3.2帶函數和小數點的計算器設計設計要求有帶函數和小數點的計算器設計,設計采用1602作為顯示。此設計有一個小數點的位置問題,如果小數點位置是變化的,比如顯示3.4或3.48,那么小數點就發生變化,稱之為“浮動”小數點; 如果小數點的位置保持不變,比如顯示3.40或3.48,稱之為“固定”小數點。市面上的計算器都是采用“浮動”小數點,編程復雜得多,本次設計采用“浮動”小數點方法。第二個設計特點就是具有函數運算,把功能鍵復用,另加一個獨立鍵,當按下獨立鍵盤S1時,表明鍵盤當作了sina、cos、tang等功能用。其設計思路是,獨立鍵S1未按下時,由于接上拉電阻,P3.0設置為輸入,則P3.0輸入為高電平,就運行四則運算程序; 獨立鍵S1按下時,則P3.0輸入為低電平,就運行函數程序了。按下復位鍵盤后,重新開始計算。當出現被除數為零時,液晶顯示“error input”。函數的運算,好的方法是加個頭文件“math.h”,該頭文件包含sina、cos、tang、ctang函數等運算。帶函數和小數點的計算器硬件電路圖如圖32所示。
圖32帶函數和小數點的計算器設計電路圖
采用8MHz晶振作為時鐘源。P4口接矩陣式鍵盤,P3.0接獨立式鍵盤。程序清單如下:
#include
#include
#define uchar unsigned char
#define uint unsigned int
#define set_rs P1OUT|=BIT3
#define clr_rs P1OUT&=~BIT3
#define set_lcden P1OUT|=BIT5
#define clr_lcden P1OUT&=~BIT5
#define dataout P2DIR=0XFF
#define dataport P2OUT
#define anjian (P3IN&BIT0)
uchar keyvalue;
uchar wei0=0,fuhao=0,flag1=0,flag2=0;
uchar tab1[]={"sin"};
uchar tab2[]={"cos"};
uchar tab3[]={"tan"};
uchar tab4[]={"="};
uchar dis_flag=0,time_1s_ok;
uint num=0;
uint time=0;
uchar dis_flag;
uint i,j;
int t,a,shu,k;
int jd,jd1,result,result1;
uint time_counter;
void int_clk()
{
unsigned char i;
BCSCTL1&=~XT2OFF; //打開XT振蕩器
BCSCTL2|=SELM1 SELS; //MCLK為8MHz,SMCLK為1MHz
do
{
IFG1&=~OFIFG; //清除振蕩器錯誤標志
for(i=0; i
_NOP(); //延時等待
}
while((IFG1&OFIFG)!=0); //如果標志為1,則繼續循環等待
IFG1&=~OFIFG;
}
void delay5ms(void)
{
unsigned int i=40000;
while (i != 0)
{
i--;
}
}
void write_com(uchar com) //1602寫命令
{
P1DIR|=BIT3 ;
P1DIR|=BIT5 ;
P2DIR=0xff;
clr_rs;
clr_lcden;
P2OUT=com;
delay5ms( );
delay5ms( );
set_lcden;
delay5ms( );
clr_lcden;
}
void write_date(uchar date) //1602寫數據
{
P1DIR|=BIT3 ;
P1DIR|=BIT5 ;
P2DIR=0xff;
set_rs;
clr_lcden;
P2OUT=date;
delay5ms( );
delay5ms( );
set_lcden;
delay5ms( );
clr_lcden;
}
void disp(unsigned char s
{
while(s > 0
{
write_date(s);
s ;
}
}
void lcddelay
{
unsigned int j;
for(j=400; j>0; j--);
}
void lcd_pos(unsigned char x,unsigned char y
{
dataport=0x80 0x40x y;
P1DIR|=BIT3 ;
P1DIR|=BIT5 ;
P2DIR=0xff;
clr_rs;
clr_lcden;
delay5ms( );
delay5ms( );
set_lcden;
delay5ms( );
clr_lcden;
}
void init( )
{
clr_lcden;
write_com(0x38);
delay5ms( );
write_com(0x0c);
delay5ms( );
write_com(0x06);
delay5ms( );
write_com(0x01);
}
void display(unsigned long int num
{
uchar dis_flag=0;
uchar table[7];
if(num0
{
dis_flag=1;
table[0]=num%10 '0';
}
else if(num9)
{
dis_flag=2;
table[0]=num/10 '0';
table[1]=num%10 '0';
}
else if(num99)
{
dis_flag=3;
table[0]=num/100 '0';
table[1]=num/10%10 '0';
table[2]=num%10 '0';
}
else if(num999)
{
dis_flag=4;
table[0]=num/1000 '0';
table[1]=num/10 '0';
table[2]=num/10%10 '0';
table[3]=num%10 '0';
}
else if(num9999)
{
dis_flag=5;
table[0]=num/10000 '0';
table[1]=num/1000%10 '0';
table[2]=num/10 '0';
table[3]=num/10%10 '0';
table[4]=num%10 '0';
}
else if(num99999)
{
dis_flag=6;
table[0]=num/100000 '0';
table[1]=num/10000%10 '0';
table[2]=num/1000%10 '0';
table[3]=num/10 '0';
table[4]=num/10%10 '0';
table[5]=num%10 '0';
}
else if(num999999)
{
dis_flag=7;
table[0]=num/1000000 '0';
table[1]=num/100000%10 '0';
table[2]=num/10000%10 '0';
table[3]=num/1000%10 '0';
table[4]=num/10 '0';
table[5]=num/10%10 '0';
table[6]=num%10 '0';
}
if((fuhao==4)&&(flag1==1
{
if(dis_flag
{
write_date('0');
delay5ms();
write_date('.');
delay5ms();
for(i=0; i
{
write_date('0');
delay5ms();
}
}
}
for(i=0; i
{
if((fuhao==1)||(fuhao==2
{
if(i==dis_flag-wei0
{
write_date('.');
delay5ms();
}
}
if(fuhao==3
{
if(i==dis_flag-wei02
{
write_date('.');
delay5ms();
}
}
if(fuhao==4
{
if(dis_flag>3
{
if(i==dis_flag-3
{
write_date('.');
delay5ms();
}
}
}
write_date(table[i]);
delay5ms();
}
}
uchar keyscan(void
{
P4OUT=0xef;
if((P4IN&0x0f)!=0x0f
{
delay5ms();
if((P4IN&0x0f)!=0x0f
{
if((P4IN&0x01)==0
keyvalue=1;
if((P4IN&0x02)==0
keyvalue=2;
if((P4IN&0x04)==0
keyvalue=3;
if((P4IN&0x08)==0
keyvalue=4;
while((P4IN&0x0f)!=0x0f);
}
}
P4OUT=0xdf;
if((P4IN&0x0f)!=0x0f
{
delay5ms();
if((P4IN&0x0f)!=0x0f
{
if((P4IN&0x01)==0
keyvalue=5;
if((P4IN&0x02)==0
keyvalue=6;
if((P4IN&0x04)==0
keyvalue=7;
if((P4IN&0x08)==0
keyvalue=8;
while((P4IN&0x0f)!=0x0f);
}
}
P4OUT=0xbf;
if((P4IN&0x0f)!=0x0f
{
delay5ms();
if((P4IN&0x0f)!=0x0f