单片机课程设计结果报告

MSP430单片机课程设计报告

数字电压表和键盘扫描

专    业:            

班    级:            

姓    名:             

学    号:           

指导老师:            

一.  设计任务及要求

1、      电压表:利用 MSP430F449 内部的 ADC 模块以及课程设计实验板接口电路,通过编程完成数字电压表功能。 结果在 LCD 上显示。芯片采用MSP430F449单片机,MSP430F449是一款功能强大的16位单片机,采用了精简指令集(RISC)结构,具有丰富的寻址方式(7 种源操作数寻址、4 种目的操作数寻址)、简洁的 27 条内核指令以及大量的模拟指令;大量的寄存器以及片内数据存储器都可参加多种运算;还有高效的查表处理指令。这些特点保证了可编制出高效率的源程序。同时它还有运算速度快、超低功耗、片内资源丰富、方便高效的开发环境等优点。通过将单片机与液晶显示屏、电位器调节等模块相连,

2、      键盘:根据课程设计实验板键盘电路,通过编程完成键盘输入功能,作为其他选题的人机交互工具。

二.原理电路图

三.实验内容

(一)设计思想:

本课题是利用MSP430单片机、LCD显示模块、电位器调节等模块的构建数字电压表。MSP430系列单片机自身内部带有 A/D转换模块,用它制作的数字电压表具有测量范围精度高、速度快、性能稳定和电路简单且工作可靠等特点,具有很好的使用价值。LCD显示模块是128×64点阵的汉字图形型液晶显示模块,可显示汉字及图形,可显示8192个中文汉字(16X16点阵)、128个字符(8X16点阵)及64X256点阵显示RAM(GDRAM)。可与CPU直接连接,可采用8位并行及串行两种连接方式。具有多种显示功能如光标显示、画面移位、睡眠模式等。。 

本设计系统结构图如下图所示

输入电路输入电路 

 

                                                               

 

系统结构图

(二)参数计算

  ADC12_A可通过引脚VREF+/VeREF+和VREF-和VeREF-分别提供VR+和VR-外部参考电压。当REFOUT=1并且该引脚提供参考电压时,需要外部存储电容器。

  ADC12_A内置参考电源,分别有六种不同的组合,从而提供符合要求的参考电压。

  ADC12_A内核是一个12位的模数转换器,能够将结果放在转换器存储中。该内核使用两个可编程的参考电压(VR+和VR-)定义转换的最大值和最小值。当输入模拟电压等于或大于VR+时,ADC12_A输出满量程值0FFFH;当输入电压小于等于VR-时,ADC12_A输出0.输入模拟电压的追中转换结果满足公式:

      NADDC=4095x(Vin-VR-)/(VR+-VR-)。

其中NADC≤4095,故可知:Vin≤VR+。

(三)编程步骤(关键步骤)

1、电压变初始化程序:

#include <msp430x44x.h>

#include <string.h>

#include <stdio.h>

#include <math.h>

//定义液晶显示笔画

#define a  (0x01)          

#define b  (0x02)

#define c  (0x10)

#define d  (0x08)

#define e  (0x40)          

#define f  (0x20)

#define g  (0x04)          

//#define h  (0x80)

//显示字符的指针

 const unsigned char LCD_Tab[] = {

                                  a+b+c+d+e+f     ,//显示 "0",  LCD_Tab[00]

                                  b+c             ,//显示 "1",  LCD_Tab[01]

                                  a+b+d+e+g       ,//显示 "2",  LCD_Tab[02]

                                  a+b+c+d+g       ,//显示 "3",  LCD_Tab[03]

                                  b+c+f+g         ,//显示 "4",  LCD_Tab[04]

                                  a+c+d+f+g       ,//显示 "5",  LCD_Tab[05]

                                  a+c+d+e+f+g     ,//显示 "6",  LCD_Tab[06]

                                  a+b+c           ,//显示 "7",  LCD_Tab[07]

                                  a+b+c+d+e+f+g   ,//显示 "8",  LCD_Tab[08]

                                  a+b+c+d+f+g     ,//显示 "9",  LCD_Tab[09]

                                  a+b+c+e+f+g     ,//显示 "A",  LCD_Tab[0A]

                                  c+d+e+f+g       ,//显示 "b",  LCD_Tab[0B]

                                  a+d+e+f         ,//显示 "C",  LCD_Tab[0C]

                                  b+c+d+e+g       ,//显示 "d",  LCD_Tab[0D]

                                  a+d+e+f+g       ,//显示 "E",  LCD_Tab[0E]

                                  a+e+f+g         ,//显示 "F",  LCD_Tab[0F]

                                  0               ,//显示 " ",  LCD_Tab[10]

                                 };

unsigned int results = 0;

unsigned int lastresults = 0;

void mInitSTDIO()           // 系统初始化          

{

  unsigned int i;

   // 主时钟初始化

   WDTCTL = WDTPW + WDTHOLD;        // stop watchdog timer

   FLL_CTL0 |= XCAP14PF;            // Configure load caps

  

   // 定时器A初始化

 TACTL = TASSEL0 + TACLR;       // ACLK, clear TAR

 TACCTL0 = CCIE;            // CCR0 interrupt enabled

 TACCR0 = 16384;            // 定时器常数(0.5秒)

 TACTL |= MC0;              // Start Timer_a in upmode

 

   // P5口初始化

   P5SEL = 0xFF;                // P5用于LCD显示

 

   // P6口初始化

   P6SEL = 1;               // P6.0用于ADC

   P3DIR |= 0xFE;               // 设置P6.1~P6.7为输出方式(临时)

 

   // ADC12初始化

   ADC12CTL0 = ADC12ON + REFON + REF2_5V + SHT0_6;// 打开ADC12, 2.5V参考电压, 设置SHT0 = 4*ADC12CLK*32

   ADC12CTL1 = SHS_0 + SHP + CONSEQ_0;      // SHS_0:采样输入信号源选用ADC12SC

                                                  // SHP:采样输入信号上升沿触发采样定时器,

                                                  // CONSEQ_0:单通道单次模式,

   ADC12MCTL0 = INCH_8 + SREF_1 + EOS;            // ref+=AVcc, channel = A3, end seq.

 

 

   ADC12IE = 0x01;              // ADC12.0通道中断使能

  

   for(i=0;i<0x3600;i++);                       //为参考电源启动提供延时

  

   ADC12CTL0 |= ENC;                // ADC12转换允许

 

   // 初始化 LCD

   LCDCTL = LCDON + LCD4MUX + LCDP0;    // 4-Mux LCD, segments S0-S15

   BTCTL = BTFRFQ1;

   for(i = 0; i < 8; i++) LCDMEM[i] = 0;    // 清除显示

}

#pragma vector=TIMERA0_VECTOR

  __interrupt void Timer_A0(void)

{

  if(abs(results-lastresults)>8){

      lastresults=results;

   }

 _BIC_SR_IRQ(LPM0_bits);        // Clear LPM0, SET BREAKPOINT HERE

}

void displayData(int data){

  LCDMEM[6] = LCD_Tab[data/1000000];

  LCDMEM[5] = LCD_Tab[data%1000000/100000];

  LCDMEM[4] = LCD_Tab[data%100000/10000];

  LCDMEM[3] = LCD_Tab[data%10000/1000];

  LCDMEM[2] = LCD_Tab[data%1000/100]+0x80; //此位需要加上小数点

  LCDMEM[1] = LCD_Tab[data%100/10];

  LCDMEM[0] = LCD_Tab[data%10];

}

void delay(){

  int j=0;

  for(;j<10000;j++);

}

//主程序

main()

{

   int i;

   mInitSTDIO();            // 系统初始化

   _EINT();             // 开启中断

   for(i = 0;i < 1000;i++);     //延时

  _BIS_SR(LPM0_bits);       // Enter LPM0

   while(1)

     {

       displayData(results);

       ADC12CTL0 |= ADC12SC;        // 开始转换

       delay();

     }

}

// ADC12 中断服务程序

#pragma vector=ADC_VECTOR

  __interrupt void ADC12ISR(void)

{

  results = 2.8*1000/4096*ADC12MEM0; //采样数值转换

 

  _BIC_SR_IRQ(LPM0_bits);               // Clear LPM0, SET BREAKPOINT HERE

}

2、  键盘初始化程序:

#include <msp430x44x.h>

#include <string.h>

#include <stdio.h>

//定义液晶显示笔画

#define a  (0x01)                     

#define b  (0x02)

#define c  (0x10)

#define d  (0x08)

#define e  (0x40)                     

#define f  (0x20)

#define g  (0x04)                     

//#define h  (0x80)

//显示字符的指针

 const unsigned char LCD_Tab[] = {

                                  a+b+c+d+e+f     ,//显示 "0", LCD_Tab[00]

                                  b+c             ,//显示 "1",         LCD_Tab[01]

                                  a+b+d+e+g       ,//显示 "2",         LCD_Tab[02]

                                  a+b+c+d+g       ,//显示 "3",         LCD_Tab[03]

                                  b+c+f+g         ,//显示 "4", LCD_Tab[04]

                                  a+c+d+f+g       ,//显示 "5", LCD_Tab[05]

                                  a+c+d+e+f+g     ,//显示 "6", LCD_Tab[06]

                                  a+b+c           ,//显示 "7",         LCD_Tab[07]

                                  a+b+c+d+e+f+g   ,//显示 "8", LCD_Tab[08]

                                  a+b+c+d+f+g     ,//显示 "9", LCD_Tab[09]

                                  a+b+c+e+f+g     ,//显示 "A", LCD_Tab[0A]   

                                  c+d+e+f+g       ,//显示 "b", LCD_Tab[0B]

                                  a+d+e+f         ,//显示 "C",         LCD_Tab[0C]

                                  b+c+d+e+g       ,//显示 "d",         LCD_Tab[0D]

                                  a+d+e+f+g       ,//显示 "E", LCD_Tab[0E]

                                  a+e+f+g         ,//显示 "F", LCD_Tab[0F]

                                  0               ,//显示 " ", LCD_Tab[10]

                                 };

int strfind(char *);

char Y[24];

signed char Step;

unsigned int ix;

unsigned char x,p3,Step_dir,str_cont;

unsigned int results,ccr0;

double dx;

void mInitSTDIO()                       // 系统初始化                          

{

 unsigned char i;

 // 主时钟初始化

 WDTCTL = WDTPW + WDTHOLD;          // stop watchdog timer

 FLL_CTL0 |= XCAP14PF;                            // Configure load caps

 // 定时器A初始化

 TACTL = TASSEL0 + TACLR;              // ACLK, clear TAR

 TACCTL0 = CCIE;                      // CCR0 interrupt enabled

 TACCR0 = 32768;                     // 定时器常数(1秒)

 TACTL |= MC0;                                   // Start Timer_a in upmode

 // 定时器B初始化

 TBCTL = TASSEL0 + TACLR;              // ACLK, clear TAR

 TBCCTL0 = CCIE;                      // CCR0 interrupt enabled

 TBCCR0 = 328;                                   // 定时器常数(1/100秒)

 TBCTL |= MC0;     

 // P1口初始化

 P1DIR = 0;                                  // 设置P1.0~P1.7为输入方式

 P1IFG = 0;                                   // 清除P1的中断标志

 P1IE = 0xFF;                               // 设置 P1.0~P1.7 中断       

 P1IES = 0xFF;                             // 设置 P1.0~P1.7 下降沿中断  

 // P2口初始化

 P2DIR |= 0xCF;                                   // 设置P2.0~P2.3,P2.6,P2.7为输出方式

  // P3口初始化

 P3DIR = 0xFF;                                     // 设置P3.0~P3.7为输出方式

 // P4口初始化

 P4DIR |= 0xFC;                                   // 设置P4.2~P4.7为输出方式

 // P5口初始化

 P5SEL = 0xFF;                             // P5用于LCD显示

 // P6口初始化

 P6SEL = 1;                                   // P6.0用于ADC

 P3DIR |= 0xFE;                                   // 设置P6.1~P6.7为输出方式(临时)

 // ADC12初始化

 ADC12CTL0 = ADC12ON + REFON + REF2_5V + SHT0_6;// 打开ADC12, 2.5V参考电压, 设置SHT0 = 4*ADC12CLK*32

 ADC12CTL1 = SHS_0 + SHP + CONSEQ_0;               // SHS_0:采样输入信号源选用ADC12SC

                                                       // SHP:采样输入信号上升沿触发采样定时器,

                                                        // CONSEQ_0:单通道单次模式,

 ADC12MCTL0 = INCH_8 + SREF_1 + EOS;            // ref+=AVcc, channel = A8, end seq.

 ADC12IE = 0x01;                                // ADC12.0通道中断使能

 ADC12CTL0 |= ENC;                                  // ADC12转换允许

 // 初始化 LCD

 LCDCTL = LCDON + LCD4MUX + LCDP0;       // 4-Mux LCD, segments S0-S15

 BTCTL = BTFRFQ1;

 for(i = 0; i < 8; i++) LCDMEM[i] = 0;        // 清除显示

//主程序

main()

{

 int ix;

 mInitSTDIO();                                     // 系统初始化

 str_cont = 0;

 Step_dir = 0;

 str[0] = 0;                

 ccr0 = 327;

 str_ok = 0;

 _EINT();                             // 开启中断

// Timer A0 中断服务程序

#pragma vector=TIMERA0_VECTOR

  __interrupt void Timer_A0(void)

{

 p3 <<= 1;

 if(p3 == 0) p3 = 1;

 P3OUT = p3;

// _BIC_SR_IRQ(LPM3_bits);            // Clear LPM3 bits from 0(SR)

 _BIC_SR_IRQ(LPM0_bits);              // Clear LPM0, SET BREAKPOINT HERE

}

// Timer B0 中断服务程序

#pragma vector=TIMERB0_VECTOR

  __interrupt void Timer_B0(void)

{

 char i,L;

 x <<= 1;                              // 键盘扫描

 if((x & 0x07) == 0) x = 1;

 P2OUT = (~x) & 0x07;

 for(i = 0; i < 0x18; i++){

    if(Y[i] < 6) Y[i]++;

    if(Y[i] == 6){

       for(L = 4; L > 0; L--) LCDMEM[L] = LCDMEM[L-1];

       LCDMEM[0] = LCD_Tab[i];

       Y[i] = 22;

      }

   }

// _BIC_SR_IRQ(LPM3_bits);            // Clear LPM3 bits from 0(SR)

 _BIC_SR_IRQ(LPM0_bits);              // Clear LPM0, SET BREAKPOINT HERE

}

// ADC12 中断服务程序

#pragma vector=ADC_VECTOR

  __interrupt void ADC12ISR(void)

{

  dx =(double)ADC12MEM0;           // Move results, IFG is cleared

//  _BIC_SR_IRQ(LPM3_bits);                 // Clear LPM3 bits from 0(SR)

  _BIC_SR_IRQ(LPM0_bits);               // Clear LPM0, SET BREAKPOINT HERE

}

// P1 中断服务程序

#pragma vector=PORT1_VECTOR

  __interrupt void P1INT(void)

{

 unsigned int scan;

// unsigned char key;

 scan = ~P2IN;

 scan &= 0x0007;

 scan <<= 8;

 scan |= P1IFG;

 switch(scan)

   {

    case 0x0101:   // "0"键键值

      Y[0] = 0;

      break;

    case 0x0102:   // "1"键键值

      Y[1] = 0;

      break;

    case 0x0104:   // "2"键键值

      Y[2] = 0;

      break;

    case 0x0108:   // "3"键键值

      Y[3] = 0;

      break;

    case 0x0110:   // "4"键键值

      Y[4] = 0;

      break;

    case 0x0120:   // "5"键键值

      Y[5] = 0;

      break;

    case 0x0140:   // "6"键键值

      Y[6] = 0;

      break;

    case 0x0180:   // "7"键键值

      Y[7] = 0;

      break;

    case 0x0201:   // "8"键键值

      Y[8] = 0;

      break;

    case 0x0202:   // "9"键键值

      Y[9] = 0;

      break;

    case 0x0204:   // "A"键键值

      Y[0x0a] = 0;

      break;

    case 0x0208:   // "B"键键值

      Y[0x0b] = 0;

      break;

    case 0x0210:   // "C"键键值

      Y[0x0c] = 0;

      break;

    case 0x0220:   // "D"键键值

      Y[0x0d] = 0;

      break;

    case 0x0240:   // "E"键键值

      Y[0x0e] = 0;

      break;

    case 0x0280:   // "F"键键值

      Y[0x0f] = 0;

      break;

    case 0x0401:   // "UP"键键值

      Y[0x10] = 0;

      break;

    case 0x0402:   // "DN"键键值

      Y[0x11] = 0;

      break;

    case 0x0404:   // "L"键键值

      Y[0x12] = 0;

      break;

    case 0x0408:   // "R"键键值

      Y[0x13] = 0;

      break;

    case 0x0410:   // "STRAT"键键值

      Y[0x14] = 0;

      break;

    case 0x0420:   // "STOP"键键值

      Y[0x15] = 0;

      break;

    case 0x0440:   // "ESC"键键值

      Y[0x16] = 0;

      break;

    case 0x0480:   // "ENTER"键键值

      Y[0x17] = 0;

      break;

    default:            // 其它情况

      LCDMEM[6] = 0;

      break;  

   }  

// if(key < 0x10)  LCDMEM[6] = LCD_Tab[key];

// else LCDMEM[6] = 0;

 P1IFG = 0;

 _BIC_SR_IRQ(LPM0_bits);              // Clear LPM3 bits from 0(SR)

}

相关推荐