资源描述
单片机课程设计
杭州电子科技大学
电子系统设计综合实验
设计报告
实验名称
1
数字频率计设计
大组号
1
小组号
49
姓名学号
徐志朗
11192127
指导教师
2013 年 5 月 15 日
摘要
在电子技术中,频率是最基本的参数之一,数字频率计具有精度高、使用方便、测量迅速、以及便于实现测量过程自动化等优点,是近代电子技术领域的重要工具之一,在许多领域得到广泛应用。本系统以超低功耗MSP430G2553单片机为核心处理芯片来测量信号的频率,通过定时器A采用计数法完成信号频率测量,并将被测频率值通过LCD12864液晶串行显示。频率可测量范围在1Hz到60KHz之间。
关键字:频率 430单片机 液晶显示 串口
1方案论证与比较
1.1测频基本方法和原理比较
方案一:使用测频法进行频率测量,测频法即在限定的时间内(如1s)检测脉冲的个数。当被测频率的范围比较高时,使用测频法比较合适。
方案二:使用测周法进行频率测量,测周法即测试限定的脉冲个数之间的时间。当被测频率的范围比较低时,使用测周法比较合适。
考虑到较高的测试频率,在此使用方案二,即测频法进行测量。
1.2 处理器的方案选择论证
本设计使用TI公司的MSP430G2553低功耗单片机为主控芯片,该单片机的I/O接口较少,但内部资源丰富,如含有10位AD转换、16位定时器/计数器、USART接口等,处理功能强大,足以胜任此次设计任务。
1.3 滞回比较电路放大器的选择
方案一:使用TI公司的OP37放大器,该放大器对信号转换速率快且稳定,适用于对高频信号的转换,但价格较高。
方案二:使用普通的LM324放大器,该放大器对信号转换速率慢,适用于对低频信号的转换,价格便宜。
考虑到三角波和正弦波在频率较高时转化为方波时对放大器的转化速率要求较高,在此使用方案一,即使用TI公司的OP37放大器作为滞回比较电路的核心转换芯片。
2系统设计
2.1总体设计
系统硬件设计方案如图2.1-1所示:
图2.1-1 硬件设计方框图
电源系统由LM7805和200V转±18V中心变压器组成,实现对MSP430G2553核心处理芯片、LCD12864液晶显示提供所需电源。
显示部分由12864液晶对频率值进行实时显示。
软件设计部分包括单片机的I/O中断和定时中断,以及液晶的驱动和显示。
该设计由硬件和软件共同实现了频率计的功能,整体设计过程可概括为:被测信号通过滞回比较电路整形为适合单片机接收的脉冲信号(方波)输入单片机,单片机通过I/O中断和定时器共同获得被测信号的频率并通过液晶对频率进行实时显示。
2.2单元电路设计
2.2.1 MSP430G2553和12864液晶引脚功能说明
2.2.1.1 MSP430G2553引脚功能说明
本次设计需要用到430单片机的1脚电源、16脚复位端、20脚接地端、配置P1.0口为待测信号输入端,P2.0为LCD片选信号端,P2.1为LCD串行数据输入\输出端,P2.2为LCD串行时钟输入\输出端,P2.3为LCD串并模式选择端,如表2.2.1.1-1所示。
表2.2.1.1-1 MSP430G2553引脚及功能说明
引脚序号
引脚名称
功能说明
1
VCC
电源正
2
P1.0
频率信号输入端
3
P1.1
1KHz方波产生引脚
5
P2.0
LCD片选信号端
6
P2.1
LCD串行数据输入\输出端
7
P2.2
LCD串行时钟输入\输出端
8
P2.3
LCD串并模式选择端
16
RST
复位脚
20
GND
电源地
2.2.1.2 LCD12864引脚功能说明
LCD12864液晶显示屏用到1、2脚,电源接口线,19、20脚背光电源接口线,15脚并行/串行接口选择,5脚串行数据口,6脚串行的同步时钟。LCD12864引脚功能如表2.2.1.2-2所示。
表2.2.1.2-2 LCD12864引脚功能说明
引脚序号
引脚名称
功能说明
1
VSS
模块的电源地
2
VDD
模块的电源正端
4
RS(CS)
并行指令/数据选择信号、串行片选信号
5
R/W(SID)
并行读写选择信号、串行的数据口
6
E(CLK)
并行使能信号、串行的同步时钟
15
PSB
PSB并/串行接口选择:H-并行,L-串行
19
LED_A
背光源正极
20
LED_K
背光源负极(0V)
2.2.2滞回比较电路设计
滞回比较电路将输入信号波形转化为脉冲信号,另外波形变换和波形整形电路实现把正弦波样的正负交替的信号波形变换成可被单片机接收的TTL信号,以便单片机对其进行频率测量,最后将测得的数据通过12864液晶显示。
滞回比较器是一个具有迟滞回环传输特性的比较器。在反相输入单门限电压比较器的基础上引入正反馈网络,就组成了具有双门限值的反相输入滞回比较器。由于反馈的作用这种比较器的门限电压是随输出电压的变化而变化的。它的灵敏度低一些,但抗干扰能力却大大提高。反相滞回比较器的电路组成如图2.2.2-1所示,如果把VI和VREF位置互换,就可以构成同相输入迟滞比较器。
图2.2.2-1 反相滞回比较器电路组成
滞回比较器又可理解为加正反馈的单限比较器。对于单限比较器,如果输入信号在门限值附近有微小的干扰,则输出电压就会产生相应的抖动(起伏),而在此电路中引入正反馈可以克服这一缺点。
整个滞回比较电路原理图如图2.2.2-2所示。
图2.2.2-2 滞回比较电路图
OP37和R4、R8组成滞回比较器,对被测信号转化为脉冲信号,二极管实现对脉冲信号进行整形,滤去负电平部分,变成可被单片机接收的TTL信号,输入到单片机,以实现频率测量。
2.2.3 显示电路设计
该频率计采用12864液晶进行显示
12864液晶显示器是一种具有 4 位/8 位并行、2 线或3 线串行多种接口方式,内部含有国标一级、二级简体中文字库的点阵图形液晶显示模块;其显示分辨率为 128×64, 内置 8192 个 16*16 点汉字,和128个16*8点 ASCII 字符集。利用该模块灵活的接口方式和简单、方便的操作指令,可构成全中文人机交互图形界面。可以显示 8×4 行 16×16 点阵的汉字。 也可完成图形显示。低电压低功耗是其又一显著特点。由该模块构成的液晶显示方案与同类型的图形点阵液晶显示模块相比,不论硬件电路结构或显示程序都要简洁得多,且该模块的价格也略低于相同点阵的图形液晶模块。
液晶的控制管脚与430单片机的连接如下图2.2.3-2所示。
图2.2.3-2 液晶控制管脚连接图
3软件设计
3.1 总体设计流程图
系统软件设计包括测量初始化模块、显示模块、定时器中断服务模块、I/O中断模块。系统软件整体流程图如图3.1-1所示。
图3.1-1 系统软件整体设计流程图
3.2 各功能子模块介绍
3.2.1 初始化模块
设备初始化包括关闭看门狗,I/O口输入/输出功能的配置,时钟初始化,端口初始化以及液晶初始化,开总中断,其流程图如图3.2.1-1所示。
3.2.1-1 系统初始化流程图
3.2.2 中断模块
首先开启定时溢出中断和I/O中断,再打开总中断,计数器开始计数,当计数溢出时进入溢出中断,且溢出次数加1,当有上升沿到来时,进入I/O中断,计算两次中断之间(一个周期内)的计数值,并转化为频率值。TA中断流程图如图3.2.2-1所示。
图3.2.2-1 TA中断流程图
I/O中断流程图如图3.2.2-2所示。
图3.2.2-2 I/O中断流程图
3.2.3 显示模块
首先根据12864液晶的时序图写出液晶驱动函数,并调用驱动函数完成在指定位置处显示字符的功能函数,这样通过定时刷新液晶屏就可以显示频率值了,而且显示位置可以根据需要任意指定。
3.2.4 串口模块
首先将出口进行初始化,然后当定时器达到1S时,串口定时向PC机发送当前测到的频率值,串口流程图如图3.2.4-1所示。
图3.2.4-1 串口流程图
4 系统测试
4.1 测试430单片机自身产生1KHz方波的频率
将模拟开关闭合,使430单片机自身产生的1KHz的方波接入被测信号接口,测试结果如表4.1-1。
表4.1-1 430单片机自身产生方波测试结果
次数
实际频率
测试频率
串口发送频率(ASCII码)
1
1KHz
991Hz
39 39 31
2
1KHz
992Hz
39 39 32
3
1KHz
992Hz
39 39 31
4.2 测试由信号发生仪产生的频率
将模拟开关断开,使信号发生仪产生方波接入被测信号接口,测试结果如表4.2-1。
表4.2-1 外部接入方波测试结果:
次数
实际频率
测试频率
串口发送频率(ASCII码)
1
100Hz
98 Hz
39 38
2
1KHz
991 Hz
39 39 31
3
20KHz
19526 Hz
31 39 35 32 36
4
35 KHz
34125Hz
33 34 31 32 35
5
55 KHz
54655 Hz
35 34 36 35 35
将模拟开关断开,使信号发生仪产生正弦波接入被测信号接口,测试结果如表4.2-2。表4.2-2 外部接入正弦波测试结果:
次数
实际频率
测试频率
串口发送频率(ASCII码)
1
100Hz
97Hz
39 37
2
1 KHz
992Hz
39 39 32
3
20 KHz
19498Hz
31 39 34 39 38
4
35 KHz
34268Hz
33 34 32 36 38
5
55 KHz
54623Hz
35 34 36 32 33
表4.2-2 外部接入正弦波测试结果
将模拟开关断开,使信号发生仪产生三角波接入被测信号接口,测试结果如表4.2-3。
表4.2-3 外部接入三角波测试结果
次数
实际频率
测试频率
串口发送频率(ASCII码)
1
100Hz
97Hz
39 37
2
1 KHz
991 Hz
39 39 31
3
20 KHz
19544Hz
31 39 35 34 34
4
35 KHz
34368Hz
33 34 33 36 38
5
55 KHz
54645Hz
35 34 36 34 35
从以上实测数据看,本设计很好地完成了设计题目中的各项要求,具有优良的性能,且实物做工精美,这说明本设计是比较成功的。
附录
附一:参考文献
[1]. 胡大可,MSP430超低功耗16位单片机原理与应用,北京航空航天大学出版社.
[2]. 童诗白,华成英,模拟电子技术基础(第四版),清华大学出版社,2006.01.
[3]. MSP430G2553DataSheet.
[4]. X2XXUserGuide.
[5]. Op37DataSheet.
附二:元器件及仪器明细表
LanchPad430开发板
1块
电源模块
1个
12864液晶屏
1个
MSP430G2553处理器
1个
USB线
1根
焊接板
3块
OP37放大器
1个
模拟开关
1个
杜邦线
若干
电阻
若干
电容
若干
附三:设计原理图
图附三-1为单片机最小系统。
附三-1 单片机最小系统:
图附三-3为滞回比较电路。
附三-3 滞回比较电路
附五:实验设计程序
/*
* 头文件
*/
#include<msp430g2553.h>
#include "stdio.h"
/*
* 全局变量的定义和宏定义
*/
unsigned int start,end;
unsigned long int F = 0;
unsigned char TA_overflow;
unsigned int TA_i = 0;
unsigned int port_i;
unsigned char tab[]={"0123456789"};
unsigned char a[8];
unsigned char int_to_string[10];
unsigned char int_array[10];
#define uchar unsigned char
#define uint unsigned int
#define CS_0 P2OUT &= ~BIT0 //片选为低电平
#define CS_1 P2OUT |= BIT0 //片选为高电平
#define SID_0 P2OUT &= ~BIT1 //串行数据输入为0
#define SID_1 P2OUT |= BIT1 //串行数据输入为1
#define SCLK_0 P2OUT &= ~BIT2 //时钟线拉低
#define SCLK_1 P2OUT |= BIT2 //时钟线拉高
#define PSB_0 P2OUT &= ~BIT3 //出行输入
#define LCD_DIR_OUT P2DIR |= BIT0 + BIT1 + BIT2 + BIT3 //4个端口设置为输出
/********************************************************************
* 名称 : SendByte
* 功能 : 发送数据
* 输入 : Dbyte
* 输出 : 无
***********************************************************************/
void SendByte(uchar Dbyte)
{
uchar i;
LCD_DIR_OUT;
for(i = 0;i < 8;i++)
{
if((Dbyte << i) & 0x80)
{
SID_1;
}
else
{
SID_0;
}
SCLK_0;
_delay_cycles(2);
SCLK_1;
}
}
/********************************************************************
* 名称 : Write_Instruction
* 功能 : 向LCD写指令
* 输入 : data
* 输出 : 无
***********************************************************************/
void Write_Instruction(uchar data)
{
LCD_DIR_OUT;
CS_1;
SendByte(0xf8);
SendByte(data & 0xf0);
SendByte((data << 4) & 0xf0);
_delay_cycles(20);
}
/********************************************************************
* 名称 : Write_Data
* 功能 :向LCD写入数据
* 输入 : data
* 输出 : 无
***********************************************************************/
void Write_Data(uchar data)
{
LCD_DIR_OUT;
CS_1;
SendByte(0xfa);
SendByte(data & 0xf0);
SendByte((data << 4) & 0xf0);
_delay_cycles(20);
}
/********************************************************************
* 名称 : LCD12864_Delay()
* 功能 : 初始化LCD12864
* 输入 : 无
* 输出 : 无
***********************************************************************/
void LCD_Init()
{
LCD_DIR_OUT; //设置输入方向为输出
PSB_0; //LCD为串行输入方式
Write_Instruction(0x30); //基本指令集
_delay_cycles(10000);
Write_Instruction(0x02); //地址归位
_delay_cycles(10000);
Write_Instruction(0x0c); //整体显示打开,游标关闭
_delay_cycles(10000);
Write_Instruction(0x01); //清除显示
_delay_cycles(10000);
Write_Instruction(0x06); //游标右移
_delay_cycles(10000);
Write_Instruction(0x80); //设定显示的起始地址
_delay_cycles(10000);
}
/********************************************************************
* 名称 : Write_Pos
* 功能 : 确定输入数据的位置
* 输入 : x,y
* 输出 : 无
***********************************************************************/
void Write_Pos(uchar x,uchar y)
{
uchar pos;
if(x == 1) //第一行显示
x = 0x80;
else if(x == 2) //第二行显示
x = 0x90;
else if(x == 3) //第三行显示
x = 0x88;
else if(x == 4) //第四行显示
x = 0x98;
pos = x + y-1;
Write_Instruction(pos);//显示地址
}
/********************************************************************
* 名称 : Write_Word_To_12864
* 功能 : 在坐标x,y处写入数据
* 输入 : x,y,*word
* 输出 : 无
***********************************************************************/
void Write_Word_To_12864(uchar x,uchar y,uchar *word)
{
uchar i;
LCD_Init();
Write_Pos(x,y);
for(i = 0;*(word+i)!='\0';i++)
{
Write_Data(word[i]);
}
}
void ShowInit()
{
Write_Word_To_12864(1,1,"频率计:");
_delay_cycles(50000);
Write_Pos(2,7);
Write_Data('H');
Write_Data('z');
_delay_cycles(10000);
}
void ShowF()
{
Write_Pos(2,4);
if(F >= 100000)
{
Write_Data(tab[F/100000]);
Write_Data(tab[F%100000/10000]);
Write_Data(tab[F%10000/1000]);
Write_Data(tab[F%1000/100]);
Write_Data(tab[F%100/10]);
Write_Data(tab[F%10]);
_delay_cycles(1000);
}
else if(F >= 10000)
{
Write_Data(tab[F/10000]);
Write_Data(tab[F%10000/1000]);
Write_Data(tab[F%1000/100]);
Write_Data(tab[F%100/10]);
Write_Data(tab[F%10]);
_delay_cycles(1000);
}
else if(F >= 1000)
{
Write_Data(tab[F/1000]);
Write_Data(tab[F%1000/100]);
Write_Data(tab[F%100/10]);
Write_Data(tab[F%10]);
_delay_cycles(1000);
}
else if(F >= 100)
{
Write_Data(tab[F/100]);
Write_Data(tab[F%100/10]);
Write_Data(tab[F%10]);
_delay_cycles(1000);
}
else if(F >= 10)
{
Write_Data(tab[F/10]);
Write_Data(tab[F%10]);
_delay_cycles(1000);
}
else
{
Write_Data(tab[F]);
_delay_cycles(1000);
}
}
/********************************************************************
* 名称 : Init_uart0
* 功能 : 初始化串口
* 输入 : 无
* 输出 : 无
***********************************************************************/
void Init_uart0()
{
UCA0CTL1|=UCSWRST; //UCA0软件复位
//UCA0CTL0&=~UC7BIT;//字符长度为8
UCA0CTL1|=UCSSEL_2;//选择系统时钟:SMCLK
UCA0BR0=0x6D; //波特率为9600
UCA0BR1=0;
UCA0MCTL=0;//UCA0MCTL=UCBRS0;
IE2=UCA0RXIE+UCA0TXIE;//开接收使能
UCA0CTL1&=~UCSWRST;
P1SEL|=BIT1+BIT2; //将P1.1 P1.2设为第二功能
P1SEL2|=BIT1+BIT2;
}
/********************************************************************
* 名称 : Uart0Sends
* 功能 : 串口发送数据
* 输入 : *s
* 输出 : 无
***********************************************************************/
void Uart0SendsData(char *s)
{
while(*s!='\0')
{
UCA0TXBUF=*s;
while((IFG2&UCA0TXIFG)==0); //查询发送是否结束
IFG2&=~UCA0TXIFG; //清除发送一标志位
s++;
}
}
/********************************************************************
* 名称 : Init_In
* 功能 :初始化外部终端
* 输入 : 无
* 输出 : 无
***********************************************************************/
void Init_In()
{
P1DIR |= BIT6;
P1DIR &= ~BIT3;
P1IES |= BIT3;
P1IE |= BIT3;
P1IFG &= ~BIT3;
_EINT();
}
void Init_Timer()
{
TACCTL0 = CCIE; // CCR0 interrupt enabled
TACCR0 = 1;
TACTL = TASSEL_1 + MC_1 + TAIE + TACLR; //up mode
}
/********************************************************************
* 名称 : Int_To_String
* 功能 :将一个int型数据转换为String型
* 输入 : now_f
* 输出 : 无
***********************************************************************/
void Int_To_String(unsigned long int now_f)
{
int j = 0;
for(j = 0; ;j++)
{
int_array[j] = now_f % 10 + 48 ;
now_f = now_f / 10;
if(now_f == 0) break;
}
int i = j ;
for(i = j , j = 0; i >= 0; i--,j++)
{
int_to_string[j] = int_array[i];
}
}
void main()
{
WDTCTL = WDTPW + WDTHOLD;
P1DIR |= BIT7; // P1.0 output
P1DIR |= BIT0;
if (CALBC1_1MHZ ==0xFF || CALDCO_1MHZ == 0xFF)
{
while(1); // If calibration constants erased
// do not load, trap CPU!!
}
//1Mhz
BCSCTL1 = CALBC1_1MHZ; // Set range
DCOCTL = CALDCO_1MHZ; // Set DCO step + modulation */
LCD_Init();
Init_In();
Init_Timer();
Init_uart0();
ShowInit();
while(1)
{
ShowF();
}
}
#pragma vector=PORT1_VECTOR
__interrupt void port_1()
{
if(P1IFG & BIT3)
{
P1OUT ^= BIT6;
port_i++;
if(port_i>=100)
{
port_i = 0;
F =(unsigned long int)((1000000*100.0)/((TA_overflow*65536)+TAR));
TA_overflow = 0;
TACTL |= TACLR;
}
}
P1IFG &= ~BIT3;
}
// Timer A0 interrupt service routine
#pragma vector=TIMER0_A0_VECTOR
__interrupt void Timer_A (void)
{
P1OUT ^= BIT7;
TA_i++;
if(TA_i == 2000)
{P1OUT ^= BIT0;
TA_i = 0;
Int_To_String(F);
unsigned char *s = int_to_string;
Uart0SendsData(s);
Uart0SendsData("1000");
}
}
#pragma vector=TIMER0_A1_VECTOR
__interrupt void Timer_A1()
{
switch(TA0IV)
{
case 2:break;
case 4:break;
case 10:TA_overflow++;break;
}
}
/********************************************************************
* 名称 : usart0_rx
* 功能:串口中断入口
***********************************************************************/
#pragma vector=USCIAB0RX_VECTOR
__interrupt void usart0_rx(void)
{
while((IFG2&UCA0RXIFG)==0);
//a=RXBUF0;
//i++;
a[0]=UCA0RXBUF;
}
21
展开阅读全文