单片机16个灯四种花样c语言,基于Proteus的MSP430单片机仿真实例5-16个花样灯控制...
一、任務要求
利用MSP430F247單片機的P1和P4端口控制16個發光二極管D1~D16,發光二極管有8種花樣顯示,顯示速度可調,由P2端口的三個按鍵控制,分別是模式按鍵、加速按鍵、減速按鍵。模式按鍵按下一次,花樣顯示模式變換一次,按下8次后循環到第一種模式,加速和減速按鍵可以控制LED的閃爍速度。
二、分析說明
按照任務要求,16個發光二極管可以組成更加豐富的花樣變換,由于MSP430單片機的每個端口是8位,因此需要兩個完整的端口來控制發光二極管,這還需要在程序中將16位的輸出轉換為兩個8位的輸出,此外,本實例還將介紹程序的模塊化設計、函數指針數組等內容。
三、電路設計
16個花樣燈控制的硬件電路如下圖所示。值得注意的是,P1和P4端口在連接到LED時,是用的網絡標號Q1~Q16來表示網絡連接關系,這樣就簡化了圖紙的連接,否則會導致圖紙上連線過多過密,影響到圖紙的簡潔和美觀。
四、程序代碼
由于16個花樣燈的功能較為復雜,將所有程序代碼寫在一個文件中不是一個好的程序設計習慣,此時一般采用模塊化編程。
所謂模塊化編程是指將一個較大的程序劃分為若干功能獨立的模塊,對各模塊進行獨立開發,然后再將這些模塊統一合并為一個完整的程序。這種方法是C語言中的面向過程的編程方法,可以縮短開發周期,提高程序的可讀性和可維護性。
在單片機程序里,程序比較小或者功能比較簡單的時候,我們不需要采用模塊化編程,但是,當程序功能復雜、涉及的資源較多的時候,模塊化編程就能體現它的優越性了。如前面寫過的閃爍燈程序、流水燈程序和花樣燈程序,每一個程序都是只用一個源文件編寫就能完成,但程序較為復雜,涉及的功能比較多,將程序全部集中在一個源文件里,將導致主體程序臃腫且雜亂。這樣做降低了程序的可讀性、可維護性和代碼的重用率。如果把這三個程序當做三個獨立的模塊放到主體程序中進行模塊化編程,效果就不一樣了。
實際上,模塊化編程就是模塊合并的過程,也是建立每個模塊的頭文件和源文件并將其加入到主體程序的過程。主體程序調用模塊的函數是通過包含模塊的頭文件來實現的,模塊的頭文件和源文件是模塊密不可分的的兩個部分,缺一不可。所以,模塊編編程必須提供每個模塊的頭文件和源文件。
下面以花樣燈為例來介紹模塊化編程。首先將16為花樣燈的程序分解為三部分,分別是主函數、按鍵程序和LED顯示程序。
1、建立模塊的源文件
在模塊化編程里,模塊的源文件是實現該模塊功能的變量定義和函數定義,不能定義main函數。建立模塊源文件的方法很多,直接在主體程序里新建一個文件,把代碼添加進去,保存為.c的文件,然后將該文件加入到主體程序;或者是在程序外建立一個記事本文件,把代碼添加進去,保存為.c文件,然后把文件添加到主體程序里,在本實例中,把鍵盤處理代碼放在key.c文件中。
程序如下。#include "msp430f247.h"
#include "stdlib.h"
#include "string.h"
#include "LedDisplay.h"
#include "key.h"
extern unsigned char RunMode;
extern unsigned char LEDDirection;
extern unsigned int SystemSpeed,SystemSpeedIndex;
extern unsigned char LEDFlag;
extern unsigned int LEDIndex;
unsigned int SpeedCode[]={1,2,3,5,8,10,14,17,20,30,
40,50,60,70,80,90,100,120,140,160,
180,200,300,400,500,600,700,800,900,1000};
unsigned char GetKey(void)
{
unsigned char KeyTemp;
unsigned char Key=0;
if((P2IN&0x07) != 0x07)
{
delayms(20);
if((P2IN&0x07) == 0x07)
return 0x00;
KeyTemp=P2IN&0x07;
if(KeyTemp == 0x06)
Key=0x01;
if(KeyTemp == 0x05)
Key=0x02;
if(KeyTemp == 0x03)
Key=0x03;
}
return Key;
}
void SetSpeed(unsigned char Speed)
{
SystemSpeed = SpeedCode[Speed];
}
void process_key(unsigned char Key)
{
if(Key&0x01)
{
LEDDirection=1;
LEDIndex=0;
LEDFlag=1;
RunMode=(RunMode+1)%8;
}
if(Key&0x02)
{
if(SystemSpeedIndex>0)
{
--SystemSpeedIndex;
SetSpeed(SystemSpeedIndex);
}
}
if(Key&0x03)
{
if(SystemSpeedIndex<28)
{
++SystemSpeedIndex;
SetSpeed(SystemSpeedIndex);
}
}
}
2、建立模塊的頭文件
模塊的頭文件就是模塊和主體程序的接口,里面是模塊源文件的函數聲明。建立頭文件的方法和建立源文件的方法類似,只是在保存的時候,把文件保存為.h格式的文件。本實例中,把鍵盤處理的源文件里的函數聲明放到文件里并保存為key.h。每個模塊的頭文件最終都要被包含在主體程序里,而且不能重復包含,否則編譯器報錯。
程序如下。/*****************************************軟件延時,主頻1M*******************/
#define CPU_F1 ((double)1000000)
#define delay_us1M(x) __delay_cycles((long)(CPU_F1*(double)x/1000000.0))
#define delay_ms1M(x) __delay_cycles((long)(CPU_F1*(double)x/1000.0))
/****************************************************************************/
unsigned char GetKey(void);
void SetSpeed(unsigned char Speed);
void process_key(unsigned char key);
3、同理,建立LED顯示控制的頭文件如下void Mode_0(void);
void Mode_1(void);
void Mode_2(void);
void Mode_3(void);
void Mode_4(void);
void Mode_5(void);
void Mode_6(void);
void Mode_7(void);
void Mode_8(void);
void LedShow(unsigned int LedState);
void delayms(unsigned int t);
4、建立LED顯示控制的C文件如下#include "msp430f247.h"
#include "stdlib.h"
#include "string.h"
#include "LedDisplay.h"
#include "key.h"
extern unsigned char RunMode;
extern unsigned char LEDDirection;
extern unsigned char LEDFlag;
extern unsigned int LEDIndex;
void (*run[8])(void)={Mode_0,Mode_1,Mode_2,Mode_3,
Mode_4,Mode_5,Mode_6,Mode_7};
void Mode_0(void)
{
LedShow(0x0001<
LEDIndex=(LEDIndex+1)%16;
}
void Mode_1(void)
{
LedShow(0x8000>>LEDIndex);
LEDIndex=(LEDIndex+1)%16;
}
void Mode_2(void)
{
if(LEDDirection) LedShow(0x0001<
else LedShow(0x8000>>LEDIndex);
if(LEDIndex==15) LEDDirection =! LEDDirection;
LEDIndex=(LEDIndex+1)%16;
}
void Mode_3(void)
{
if(LEDDirection)
LedShow(~(0x0001<
else
LedShow(~(0x8000>>LEDIndex));
if(LEDIndex==15)
LEDDirection =! LEDDirection;
LEDIndex=(LEDIndex+1)%16;
}
void Mode_4(void)
{
if(LEDDirection)
{
if(LEDFlag)
LedShow(0xfffe<
else
LedShow(~(0x7fff>>LEDIndex));
}
else
{
if(LEDFlag)
LedShow(0x7fff>>LEDIndex);
else
LedShow(~(0xfffe<
}
if(LEDIndex==15)
{
LEDDirection =! LEDDirection;
if(LEDDirection) LEDFlag =! LEDFlag;
}
LEDIndex=(LEDIndex+1)%16;
}
void Mode_5(void)
{
if(LEDDirection)
LedShow(0x000f<
else
LedShow(0xf000>>LEDIndex);
if(LEDIndex==15)
LEDDirection =! LEDDirection;
LEDIndex=(LEDIndex+1)%16;
}
void Mode_6(void)
{
if(LEDDirection)
LedShow(~(0x000f<
else
LedShow(~(0xf000>>LEDIndex));
if(LEDIndex==15)
LEDDirection =! LEDDirection;
LEDIndex=(LEDIndex+1)%16;
}
void Mode_7(void)
{
if(LEDDirection)
LedShow(0x003f<
else
LedShow(0xfc00>>LEDIndex);
if(LEDIndex==15)
LEDDirection =! LEDDirection;
LEDIndex=(LEDIndex+1)%16;
}
void Mode_8(void)
{
LedShow(++LEDIndex);
}
void LedShow(unsigned int LedState)
{
P1OUT=~(LedState&0x00ff);
P4OUT=~((LedState>>8)&0x00ff);
}
void delayms(unsigned int t)
{
unsigned int i;
while(t--)
{
for(i=1000;i>0;i--);
if((P2IN&0x07) != 0x07) break;
}
}
5、在主程序里包含模塊的頭文件,完成程序總體設計,把上面的key.h和LedDisplay.h分別添加到主程序頭部,如下圖所示,
主程序如下
五、程序說明
從主程序看,代碼非常簡潔,便與編程人員理解和修改,更重要的是鍵盤處理程序和顯示控制程序可以重復適用于其它設計中。
特別要指出的是在顯示控制程序中有一行代碼。void (*run[8])(void)={Mode_0,Mode_1,Mode_2,Mode_3,
Mode_4,Mode_5,Mode_6,Mode_7};
這些代碼定義了一個函數指針數組,將8個顯示模式的函數地址保存在run數組中,該數組保存的是函數的指針,在主程序中用 run[RunMode]();進入不同的顯示模式。RunMode為顯示模式變量,可以通過模式按鍵修改
六、仿真結果與分析
裝載程序后,即可點擊運行按鈕觀察程序運行結果,并根據運行結果判斷程序是否達到設計初衷。
總結
以上是生活随笔為你收集整理的单片机16个灯四种花样c语言,基于Proteus的MSP430单片机仿真实例5-16个花样灯控制...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql能够跨平台使用吗_Mysql跨
- 下一篇: 消防电气IP防护等级如何定义和解读