资源描述
燕山大学
《嵌入式智能仪表》三级项目设计说明书
题目: 频率发生器设计
学院(系): 电气工程学院
年级专业: 13仪表一班
学生姓名:
小组成员:
小 组: 第一组
指导教师: 郝晓辰 教授
燕 山 大 学 三级项目设计说明书
摘要
本系统以低功耗单片机stm32为主控器件,分为微控制器、DA转换器、功率放大等模块,实现了一个能产生任意频率波形的频率发生器。本设计利用单片机生成各种波形的数据,将数据传输给RAM存储器,通过后级的DA转换器实现波形的产生。系统输入波形参数,频率1HZ步进可调,峰-峰值可在0到10V之间任意调节。电路设计条理清晰,人机交互界面友好,控制方便,很好地完成了题目的所有基本和发挥要求。
前言
智能仪器是含有微型计算机或者微型处理器的测量仪器,拥有对数据的存储运算逻辑判断及自动化操作等功能。智能仪器的出现,极大地扩充了传统仪器的应用范围。智能仪器凭借其体积小、功能强、功耗低等优势,迅速地在家用电器、科研单位和工业企业中得到了广泛的应用。近年来,智能化测量控制仪表的发展尤为迅速,为经济发展提供了巨大推动力。进入互联网时代,智能仪器向着微型化、多功能、人工智能化、网络化发展,在越来越多的领域发挥了不可替代的作用。
实验内容
1.设计放大器电路。
2.设计嵌入式系统电路及程序,实现频率发生器基本功能,可以产生三种标准波形:正玄波、三角波和方波。
3.编写嵌入式系统程序,实现函数频率发生器功能,可以对标准波形设计频率、周期、最大值、最小值、峰峰值、偏移量和方波占空比。
4.编写嵌入式系统程序,实现随机频率发生器功能,输出波形。
实验设备
1.示波器、信号发生器、万用表
2.STC单片机开发板、C8051F开发板、STM32开发板
实验器件: STM32F103ZET6、ADUC7026
实验方案
(1)波形生成方案
采用STM32单片机生成波形,由于是软件滤波,所以不会有寄生的高次谐波分量,生成的波形比较纯净。它的特点是价格低、性能高,在低频范围内稳定性好、操作方便、体积小、耗电少。
采用此方案既可满足课程设计的基本要求又能充分发挥其优势,电路简单,易控制,性价比高。
(2)任意波形的生成原理
采用键盘输入,这是最基本的方法。优点是输入值精确。但用户自定义输入时无法自由输入想要的特殊波形,而且输入数据繁琐,操作麻烦,由于实现相对简单,故本实验采用该方案。
系统设计分析
(1)硬件部分
STM32
液晶屏
D/A
运放
示波器
键盘输入控制
运算放大器电路
R1是耦合电阻,R2,R3都为分压式反馈电阻。R2和R1的电压比例为1:2,OUT2的电压为-5v~0v,在第二级运放中要把-5v~0v之间的电压转变为-5v~5v,即第一级运放转换成电压量的值没增加或减少1v,第二级运放产生的电压就减少或增加2v。
(2)微控制器软件实现
微控制器主要用于完成数据的采集,显示以及处理,生成各种波形数据,本系统采样256个数据,采用8位DA转换器,因此RAM地址位设置为8位,数据位设置为8位。微控制器先进行数据收集处理,生成各种波形的归一化数据,然后存储在256位的数组里,根据幅值要求乘以相应的系数,最终生成可以存放在RAM里的数据。
本系统采用12位DA转换器,最大输出电压为5Vpp,功率放大为2倍,所以系统最大的输出电压可以达到10Vpp,可计算出最小电压分辨率为:
主流程
初始化
液晶显示
键盘输入处理
判断波形
方
波
正
弦
波
三
角
波
锯
齿
波
中断返回
定时中断开始
电压分辨率:K=10/4096(V)
(1)是波形发生器的主流图,由系统初始化和人机交互模块组成,其中液晶显示子模块和键盘输入处理子模块占用单片机主要处理时间,单片机反复运行该模块程序人机交互模块相当于系统的监控程序;
(2)是定时中断服务流程图,波形发生模块放置在定时中断服务程序中,系统每隔一定时间,产生一个定时中断,暂停主流程运行,转到定时中断服务程序起始处,执行波形发生模块,该模块输出一个样值后,结束此次中断服务,返回主流程断点处继续运行。反复多次定时中断服务,从而完成波形生成。
(3)键盘输入处理子模块
在具体实现时,键值识别部分作为主程序,键功能处理部分作为子程序,它们之间的关系是主程序调用子程序。键盘的工作过程:
1)扫描键盘,获得列扫描码和行状态码,从而确定被按下的按键的键值;
2)根据键值,通过散转表,跳转到相应的键功能处理部分;
3)进入键处理部分,完成键功能;
4) 完成一次键输入工作
通过键盘对单片机系统进行设置,每按一次键,键盘都会有上述的处理过程,每次仅能完成一个键功能。在实际设置波形参数时,一个参数需要多个键功能来实现,那么相应的键盘也要多次完成键值识别,跳转键处理的工作过程。
(4)函数参数设置
1)正弦波归一化数据生成函数
S(t)=sin(t) /(2K)
2)三角波归一化数据生成函数
T(t)=t/(63 *2K) (t<64)
T(t)=(127-t)/(63 *2K) (64<t<128)
T(t)=(t-128)/(63 *2K) (128<t<192)
T(t)=(255-t)/(63 *2K) (192<t<256)
3)方波归一化数据生成函数
根据电压分辨率可以得出方波归一化数据生成函数为:
F(t)= 1/(2k) (0<t<128)
F(t)= - 1/(2k) (128<t<256)
4)5次谐波数据的生成函数
W(t)=a*sin(t)+b*sin(2t+m)+c*sin(3t+n)+d*sin(4t+p)+ e*sin(5t+q)
此函数要求幅值和相位参数:a.b.c.d.e.m.n.p.q
5)正弦波、方波、三角波线性组合波数据生成函数
D(t)=a*S(t)+ b*F(t+m)+ c*T(t+n)
(5)实验参考程序
/*----------------------------------------------------------------------------
* 功 能 :STM32 DAC 数模转换(正弦波/矩形波/三角波)输出实验
* 说 明 :按 SW5 输出正弦波 / 按 SW4 输出矩形波 / 按 SW3 输出三角波, 输出端口 PA4
*----------------------------------------------------------------------------*/
#include <stdio.h>
#include <stm32f10x_lib.h> // STM32F10x Library Definitions
#include "STM32_Reg.h" // STM32 register and bit Definitions
#include "STM32_Init.h" // STM32 Initialization
#include "common.h"
#include "sine_wave_1024.h"
// 输出端口 : PA4
#define SINE_WAVE 1//sine 正弦波
#define RECT_WAVE 2//rectangular 矩形波
#define HACKLE_WAVE 3//hackle 三角波
UINT8 flag = 0;
UINT8 func = SINE_WAVE;
/*----------------------------------------------------------------------------
MAIN function
*----------------------------------------------------------------------------*/
int main (void)
{
UINT16 i = 0;
UINT32 *pDAC_BASE = (UINT32 *)DAC_BASE;
stm32_Init(); // STM32 setup
LED_Init();
//打开DAC时钟使能
RCC->APB1ENR |= (UINT32)(1 << 29);
//设置DAC控制参数 *(pDAC_BASE + 0x00) = (0x01 << 0)| (0x00 << 2) | (0x04 << 3) | (0x03 << 6) | (0x0b << 8);
*(pDAC_BASE + 0x04) = 0x01
printf(" --------------- Program start --------------- \r\n");
while (TRUE) // Loop forever
{
if(!Get_SW5())
{
func = SINE_WAVE;
}
else if(!Get_SW4())
{
func = RECT_WAVE;
}
else if(!Get_SW3())
{
func = HACKLE_WAVE;
}
switch(func)
{
case SINE_WAVE:
//-------------------------------------------------------------
#ifdef SINE_WAVE
if(i < 1024) i+=2;
else i = 0;
*(pDAC_BASE + 0x08) = Sine_WAVE[i] << 4;
#endif
//-------------------------------------------------------------
break;
case RECT_WAVE:
#ifdef RECT_WAVE
for(i=0;i<2000;i++)
*(pDAC_BASE + 0x08) = 0x0fff;
for(i=0;i<2000;i++)
*(pDAC_BASE + 0x08) = 0;
#endif
//-------------------------------------------------------------
break;
case HACKLE_WAVE:
#ifdef HACKLE_WAVE
if(flag)
{
flag = 0;
while(TRUE)
{
if(i < 4096) i += 1;
else break;
*(pDAC_BASE + 0x08) = i;
}
}
else
{
flag = 1;
while(TRUE)
{
if(i > 0) i -= 1;
else break;
*(pDAC_BASE + 0x08) = i;
}
}
#endif
break;
default:
break;
}
//-------------------------------------------------------------
} // end while
} // end main
/*----------------------------------------------------------------------------
* 设置方向
*----------------------------------------------------------------------------*/
void Set_IO_direction(UINT8 PORT, UINT8 GPIO, UINT8 Value)
{
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
if(PORT == PORT_A)
{
if(GPIO < 8)
{
GPIOA->CRL &= ~(0x0f << (GPIO * 4)); //Clr used bit
GPIOA->CRL |= (Value << (GPIO * 4)); //Set used bit
}
else
{
GPIOA->CRH &= ~(0x0f << (GPIO * 4 - 8 * 4));//Clr used bit
GPIOA->CRH |= (Value << (GPIO * 4 - 8 * 4));//Set used bit
}
}
if(PORT == PORT_B)
{
if(GPIO < 8)
{
GPIOB->CRL &= ~(0x0f << (GPIO * 4)); //Clr used bit
GPIOB->CRL |= (Value << (GPIO * 4)); //Set used bit
}
else
{
GPIOB->CRH &= ~(0x0f << (GPIO * 4 - 8 * 4));//Clr used bit
GPIOB->CRH |= (Value << (GPIO * 4 - 8 * 4));//Set used bit
}
}
if(PORT == PORT_C)
{
if(GPIO < 8)
{
GPIOC->CRL &= ~(0x0f << (GPIO * 4)); //Clr used bit
GPIOC->CRL |= (Value << (GPIO * 4)); //Set used bit
}
else
{
GPIOC->CRH &= ~(0x0f << (GPIO * 4 - 8 * 4));//Clr used bit
GPIOC->CRH |= (Value << (GPIO * 4 - 8 * 4));//Set used bit
}
}
if(PORT == PORT_D)
{
if(GPIO < 8)
{
GPIOD->CRL &= ~(0x0f << (GPIO * 4)); //Clr used bit
GPIOD->CRL |= (Value << (GPIO * 4)); //Set used bit
}
else
{
GPIOD->CRH &= ~(0x0f << (GPIO * 4 - 8 * 4));//Clr used bit
GPIOD->CRH |= (Value << (GPIO * 4 - 8 * 4));//Set used bit
}
}
if(PORT == PORT_E)
{
if(GPIO < 8)
{
GPIOE->CRL &= ~(0x0f << (GPIO * 4)); //Clr used bit
GPIOE->CRL |= (Value << (GPIO * 4)); //Set used bit
}
else
{
GPIOE->CRH &= ~(0x0f << (GPIO * 4 - 8 * 4));//Clr used bit
GPIOE->CRH |= (Value << (GPIO * 4 - 8 * 4));//Set used bit
}
}
}
/*----------------------------------------------------------------------------
SendChar
Write character to Serial Port.
*----------------------------------------------------------------------------*/
int SendChar (int ch) {
while (!(USART2->SR & USART_FLAG_TXE));
USART2->DR = (ch & 0x1FF);
return (ch);
}
/*----------------------------------------------------------------------------
GetKey
Read character to Serial Port.
*----------------------------------------------------------------------------*/
int GetKey (void) {
while (!(USART2->SR & USART_FLAG_RXNE));
return ((int)(USART2->DR & 0x1FF));
}
void LED_Init(void)
{
Set_IO_direction(PORT_E,LED1,OUTPUT);
Set_IO_direction(PORT_E,LED2,OUTPUT);
Set_IO_direction(PORT_E,LED3,OUTPUT);
Set_IO_direction(PORT_E,LED4,OUTPUT);
Set_IO_direction(PORT_B,SW2,INPUT);
Set_IO_direction(PORT_B,SW3,INPUT);
Set_IO_direction(PORT_E,SW4,INPUT);
Set_IO_direction(PORT_E,SW5,INPUT);
Turn_OFF_LED1();
Turn_OFF_LED2();
Turn_OFF_LED3();
Turn_OFF_LED4();
}
/*----------------------------------------------------------------------------
insert a delay time.
*----------------------------------------------------------------------------*/
void delay(unsigned int nCount)
{
for(; nCount != 0; nCount--);
}
心得体会
通过这次三级项目,我们小组学会了频率发生器的设计方法,对频率发生器的工作原理和使用方法也有了更深刻的理解。在对理论的运用中,提高了我们的素质,在设计的过程中,同学们积极查阅相关资料,在理解的基础上运用到设计中,在交流中大家提出意见,对团队的进步与成长给了很大的帮助。
在此,向给我们提供帮助的同学们以及郝老师,表示真诚的谢意,感谢你们对我们小组的细心指导。
小组分工
参考文献
《智能仪器设计》 丁国清,陈欣
《智能仪器》 付华
《基于STM32的信号发生器设计》 百度文库
共 页 第 页
展开阅读全文