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)
}
机械与车辆学院单片机课程设计报告20xx20xx学年第一学期课程设计题目水塔水位控制系统姓名学号班级指导老师职称时间成绩单片机课程…
物理与机电学院课程设计报告课程名称:单片机课程设计系部:物理与机电工程学院专业班级:07级电子信息工程(1)班完成时间:20XX年…
成绩单片机原理及应用课程设计课程名ltlt单片机原理及应用gtgt学部专业学号姓名指导教师日期20xx年06月一设计任务与要求1任…
井冈山大学机电工程学院单片机课程设计报告课程名称单片机设计题目流水灯姓名覃家应陈东阳专业生物医学工程班级10级医工本一班学号100…
单片机课程设计示例交通灯控制系统设计一总体设计1设计要求交通灯的任务要求为模拟十字路口的交通灯的亮灭及闪烁基本工作原理根据交通灯的…
学院:专业班级:姓名:指导教师:设计时间:51单片机课程设计一、设计任务与要求1.任务:制作并调试51单片机学习板2.要求:(1)…
51单片机课程设计报告学院:专业班级:姓名:指导教师:设计时间:51单片机课程设计一、设计任务与要求1.任务:制作并调试51单片机…
江南大学课程名称设计题目班级姓名指导教师物联网工程学院课程设计报告单片机原理及应用基于单片机的步进电机控制器设计号评分20xx年6…
一6该课程设计是利用MCS51单片机内部的定时计数器中断系统以及行列键盘和LED显示器等部件设计一个单片机电子时钟设计的电子时钟通…
内容提要单片微型计算机简称单片机是典型的嵌入式微控制器常用英文字母的缩写MCU表示单片机它最早是被用在工业控制领域单片机由芯片内仅…
单片机课程设计心得体会:这个学期的单片机课已经早早的上完了,但是理论纯属理论,没有与实践的结合总让我们学的不踏实,感觉没有达到学以…