练习三A/D、D/A的使用与调试报告
苑振涛张博晨闫陶
2011年7月21日
摘要
本设计基于EasyCortex M3-1752系统为核心,主要运用了系统内部A/D、D/A芯片,显示部分采用了12864点阵液晶显示模块。本系统通过内部A/D、D/A芯片的调用实现直流电压和正弦波的幅值及频率的识别与稳定输出。
目录
一.设计要求与任务(系统设计) (4)
二.总体方案及论证(系统设计) (4)
三.系统硬件设计(单元设计) (4)
四.系统测试与测试结果 (8)
五.结论 (10)
六.参考资料 (11)
附录 (11)
一.设计要求与任务(系统设计)
利用常用A/D、D/A与MCU系统连接及使用(数据采集、显示)
二.总体方案及论证(系统设计)
本设计使用了EasyCortex M3-1752系统为核心,运用了系统内部A/D、D/A芯片,显示部分采用了12864点阵液晶显示模块。除此之外,本设计还包括了峰值检波电路。
系统方框图
三.系统硬件设计(单元设计)
主控部分
LPC1700系列ARM是基于第二代ARM Cortex-M3内核的微控制器,是为嵌入式系统应用而设计的高性能、低功耗的32位微处理器,适用于仪器仪表、工业通讯、电机控制、灯光控制、报警系统等领域。其操作频率高达120MHz,采用3级流水线和哈佛结构,带独立的本地指令和数据总线以及用于外设的低性能的第三条总线,使得代码执行速度高达1.25MIPS/MHz,并包含1个支持随机跳转的内部预取指单元。LPC1700系列ARM增加了一个专用的Flash存储器加速模块,使得在Flash中运行代码能够达到较理想的性能。最高配置包括512KB片内Flash程序存储器、96KB片内SRAM、4KB片内EEPROM、8通道GPDMA控制器、4个32位通用定时器、一个8通道12位ADC、1个10位DAC、1路电机控制PWM输出(MCPWM)、1个正交编码器接口、6路通用PWM输出、1个看门狗定时器以及一个独立供电的超低功耗RTC。
ADC部分
A/D转换器的基本时钟由APB时钟提供。A/D转换器包含一个可编程的分频器,它可以将APB时钟调整为主次逼近转换所需的时钟(最大可达13Mhz)。并且,完全满足精度要求的转换需要65个这样的时钟。具有掉电模式,测量范围:0~VREFP (通常为3V;不超过VDDA),12位转换时间为200KHz。一个或多个输入的Burst转换模式,可选择由输入跳变或定时器匹配信号触发转换。
使用以下寄存器来配置ADC:
1)功率:在寄存器PCONP中置位PCADC。
注:复位后,ADC被禁能。若要使能ADC,首先将位PCADC置位然后使能寄存器AD0CR中的ADC(即位PDN,见表29.3)。若要禁能ADC,必须先将位PDN清零,再将位PCADC清零。
2)时钟:在寄存器PCLK_SEL0中选择PCLK_ADC,若要调节ADC的时钟频率,请参见表29.3中关于位CLKDIV的描述。
3)引脚:通过寄存器PINSEL来使能ADC0引脚。通过寄存器PINMODE来选择带ADC 功能的引脚的模式(请参考“引脚连接模块”章节的“寄存器描述”小节)。
4)中断:若要使能ADC中断,请参见表29.7。利用相应的中断置位使能寄存器使能NVIC 中的ADC中断或禁止ADC中断。
DAC部分
使用以下寄存器来配置DAC:
1)电源:DAC的电源总是开启的。
2)时钟:在寄存器PCLK_SEL0中选择PCLK_DAC。
3)引脚:通过寄存器PINSEL来使能DAC引脚。通过寄存器PINMODE来选择带DAC功能的引脚的模式(请见“引脚连接模块”章节的“寄存器描述”小节),必须在访问DAC寄存器之前选择好引脚的模式。
4)DMA:DAC可以连接到GPDMA控制器(请见“DMA控制”小节)。
下表对每个DAC相关的引脚进行了简要总结。
峰值滤波部分
电路原理图
实物电路图
四.系统测试与测试结果
实物连接图
正弦波形识别显示
输出波形
直流显示
直流输出
五.结论
本设计可识别输入电压范围为0-3V,可识别频率范围为0-7MHz;输出电压范围为0-3V,输出频率范围为0-3.5K,基本满足题目要求。原有设计中的检波部分功能尚未
实现。
六.参考资料
附录
主程序
#include "..\config.h"
/***************************************************************** ****************************************
宏定义
***************************************************************** ****************************************/
#define uchar unsigned char
#define uint unsigned int
uchar Gain=0,lcdflg=0,adflg=0,wavecount=0;
INT32U count,pkp;
#define initdata 0x00b4
#define varydata 0x0022
#define KEY1 (1ul << 10) /* P2.10连接KEY1 */
#define KEY2 (1ul << 0)
/* P2.10连接KEY1 */
#define KEY3 (1ul << 1) /* P2.10连接KEY1 */
#define KEY4 (1ul << 4) /* P2.10连接KEY1 */
#define BIT(x) (1<<(x))
////************** 12864 端口定义及控制
#define CS 0 //P0.0 RS
#define SID 1 //P0.1 RW
#define SCLK 2 //P0.2 E
#define Set_CS() FIO0SET|=BIT(0); //P0.0置1
#define Set_SID() FIO0SET|=BIT(1); //P0.1置1
#define Set_SCLK() FIO0SET|=BIT(2); //P0.2置1
#define Clr_CS() FIO0CLR|=BIT(0); //P0.0置0
#define Clr_SID() FIO0CLR|=BIT(1); //P0.1置0
#define Clr_SCLK() FIO0CLR|=BIT(2); //P0.2置0
char init1[] = {"基于:LPC175x"};
char init2[] = {" LCD测试"};
char init3[] = {"峰值:"};
char init4[] = {"频率:"};
char init8[] = {0,0,0,0,0,0,0};
char init9[] = {"Hz"};
char init10[] = {"mv"};
INT16U const sin_tab[250]={
//输出电压从0到最大值(正弦波1/4部分)
0x80,0x83,0x86,0x89,0x8d,0x90,0x93,0x96,0x99,0x9c,0x9f,0xa2,0xa5,0xa8 ,0xab,0xae,0xb1,0xb4,0xb7,0xba,0xbc,
0xbf,0xc2,0xc5,0xc7,0xca,0xcc,0xcf,0xd1,0xd4,0xd6,0xd8,0xda,0xdd,0xdf,0 xe1,0xe3,0xe5,0xe7,0xe9,0xea,0xec,
0xee,0xef,0xf1,0xf2,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfd ,0xfe,0xff,0xff,0xff,
//输出电压从最大值到0(正弦波1/4部分)
0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xfd,0xfd,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7,0x f6,0xf5,0xf4,0xf2,0xf1,0xef,
0xee,0xec,0xea,0xe9,0xe7,0xe5,0xe3,0xe1,0xde,0xdd,0xda,0xd8,0xd6,0xd4, 0xd1,0xcf,0xcc,0xca,0xc7,0xc5,0xc2,
0xbf,0xbc,0xba,0xb7,0xb4,0xb1,0xae,0xab,0xa8,0xa5,0xa2,0x9f,0x9c,0x99 , 0x96,0x93,0x90,0x8d,0x89,0x86,0x83,0x80,
//输出电压从0到最小值(正弦波1/4部分)
0x80,0x7c,0x79,0x76,0x72,0x6f,0x6c,0x69,0x66,0x63,0x60,0x5d,0x5a,0x57 ,0x55,0x51,0x4e,0x4c,0x48,0x45,0x43,
0x40,0x3d,0x3a,0x38,0x35,0x33,0x30,0x2e,0x2b,0x29,0x27,0x25,0x22,0x2
0,0x1e,0x1c,0x1a,0x18,0x16 ,0x15,0x13,
0x11,0x10,0x0e,0x0d,0x0b,0x0a,0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02 ,0x02,0x01,0x00,0x00,0x00,
//输出电压从最小值到0(正弦波1/4部分)
0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02 ,0x02,0x03,0x04,0x05,0x06,0x0 7,0x08,0x09,0x0a,0x0b,0x0d,0x0e,0x10,
0x11,0x13,0x15 ,0x16,0x18,0x1a,0x1c,0x1e,0x20,0x22,0x25,0x27,0x29,0x2 b,0x2e,0x30,0x33,0x35,0x38,0x3a,0x3d,
0x40,0x43,0x45,0x48,0x4c,0x4e,0x51,0x55,0x57,0x5a,0x5d,0x60,0x63,0x66 ,0x69,0x6c,0x6f,0x72,0x76,0x79,0x7c,0x80};
//***************** 12864 函数声明
void nop(void);
void Delay(uint a); //延时子程序
void Lcd_WriteDat(char RW, char RS,uchar W_data);
void Lcd_WriteCmd(uint W_bits);
void LCD_Init(void);
void Lcd_DispLine(uchar y,uchar x ,char *p);
void DIP_Init(void);
//**************************************************************** *****************************************
//** Function name: Delay()延时ms
//** Function name: nop() 延时us
//**************************************************************** *****************************************/
__inline void Delay(uint a)
{
uint i;
while( --a != 0)
{ for(i = 0; i<5200; i++);}
}
void nop()
{
uint i;
for(i=1;i<12;i++);
}
//**************************************************************** ********************************************
////////////////// 12864 控制程序
///////////////////
//**************************************************************** ********************************************/
void LCD_Init(void)
{
uchar cmd;
cmd=0x30; //功能设置8位数据,基本指令
Lcd_WriteDat(0,0,cmd);
Delay(2);
cmd=0x0C; //显示状态ON,游标OFF,反白OFF
Lcd_WriteDat(0,0,cmd); //写指令
Delay(2);
cmd=0x01; //清除显示
Lcd_WriteDat(0,0,cmd); //写指令
Delay(2);
cmd=0x02; //地址归位
Lcd_WriteDat(0,0,cmd); //写指令
Delay(2);
cmd=0x80; //设置DDRAM地址
Lcd_WriteDat(0,0,cmd); //写指令
Delay(2); //延时
}
void Lcd_WriteDat(char RW, char RS,uchar W_data) //xie shu ju 函数作用:写一个字节的数据到12864液晶,包括指令和数据
{
uint H_data,L_data,S_ID = 0xf8; //11111RWRS0
if(RW == 0)
{ S_ID &=~ 0x04; }
else //if(RW==1)
{ S_ID |= 0X04; }
if(RS == 0)
{ S_ID &=~ 0x02; }
else //if(RS==1)
{ S_ID |= 0X02; }
H_data = W_data;
H_data &= 0xf0; //屏蔽低4位的数据
L_data = W_data; //xxxx0000格式
L_data &= 0x0f; //屏蔽高4位的数据
L_data <<= 4; //xxxx0000格式
Set_CS();
Lcd_WriteCmd(S_ID); //发送S_ID
Lcd_WriteCmd(H_data); //发送H_data
Lcd_WriteCmd(L_data); //发送L_data
Clr_CS();
}
void Lcd_WriteCmd(uint W_bits) //函数作用:负责串行输出8个bit位xie di zhi
{
uint i,Temp_data;
for(i=0; i<8; i++)
{
Temp_data = W_bits;
Temp_data <<= i;
if((Temp_data&0x80)==0)
{ Clr_SID(); }
else
{ Set_SID(); }
nop();
Set_SCLK();
nop();
nop();
Clr_SCLK();
nop();
Clr_SID();
}
}
void Lcd_SetPos(uchar y,uchar x) //设置写入位置
{
if(y == 0)
{ Lcd_WriteDat(0,0,(0x80+x)); }
if(y == 1)
{ Lcd_WriteDat(0,0,(0x90+x)); }
if(y == 2)
{ Lcd_WriteDat(0,0,(0x88+x)); }
if(y == 3)
{ Lcd_WriteDat(0,0,(0x98+x)); }
}
void Lcd_DispLine(uchar y,uchar x ,char *p) //函数作用:写入字符串{
Lcd_SetPos(y,x);
while(*p != 0)
{ Lcd_WriteDat(0,1,*p++); //利用指针调用数组里的数据
Delay(1); }
}
void DIP_Init(void) //显示
{
Lcd_DispLine(0, 0, init1); //第一行
Lcd_DispLine(1, 0, init2); //第二行
Lcd_DispLine(2, 0, init3);
Lcd_DispLine(3, 0, init4);
}
/***************************************************************** ****************************************
** Function name: myDelay
** Descriptions: 软件延时
** input parameters: ulTime
** output parameters: 无
** Returned value: 无
***************************************************************** ****************************************/
void myDelay (INT32U ulTime)
{
INT32U i;
i = 0;
while (ulTime--) {
for (i = 0; i < 5000; i++);
}
}
/***************************************************************** ****************************************
* Function name: adcInit
* Descriptions: ADC初始化,转换时钟为13MHz,突发模式
* input parameters: 无
* output parameters: 无
* Returned value: 无
***************************************************************** ****************************************/
void adcInit (void)
{
INT32U ulTemp;
PCONP |= 1 << 12;
/* 打开ADC的功率控制位*/
ulTemp = (24000000 / (13000000));
ulTemp = (1 << 2) /* 选择AD0.2为AD输入引脚*/
|(( ulTemp) << 8) /* 转换时钟为13MHz */
|(1 << 16)
/* BURST=1,使用Burst模式,*/
/* 让硬件不断地进行转换*/
|(0 << 17)
/* CLKS=0, 使用11clock转换*/
|(1 << 21) /* PDN = 1,正常工作模式*/
|(0 << 24);
/* START=0,在Burst模式下,*/
/* 起始位(bit24~26)必须为0 */
AD0CR = ulTemp;
}
/***************************************************************** ****************************************
* Function Name: timer0Isr
* Description: TIMER0 中断处理函数
* Input: 无
* Output: 无
* Return: 无
***************************************************************** ****************************************/
void timer0Isr (void)
{
T0IR = 0x01;
/* 清除中断标志*/
if(count==0)
{
DACR = ((pkp/2*1024/3000) << 6);
}
else{
//DACR = ((4*sin_tab[wavecount++]*pkp/3000) << 6);
DACR = ((4*sin_tab[wavecount++]) << 6);
if(wavecount>=250)
wavecount=0;
}
}
/***************************************************************** ****************************************
* Function Name: timer2Isr
* Description: TIMER2 中断处理函数
* Input: 无
* Output: 无
* Return: 无
***************************************************************** ****************************************/
void timer3Isr (void)
{
T3IR = 0x01;
/* 清除中断标志*/
count = T1TC;
T1TC = 0;
lcdflg=1;
adflg=1;
T0TCR = 0x02;
if(count!=0)
T0MR0 = FPCLK/250/count;
else
T0MR0 = FPCLK/250;
T0TCR = 0x01;
}
/***************************************************************** ****************************************
** Function name: timer0Init
** Descriptions: 定时器0初始化程序
** input parameters: 无
** output parameters: 无
** Returned value: da输出数据定时器
***************************************************************** ****************************************/
void timer0Init (void)
{
PCONP |= 1 << 1;
T0TCR = 0x02;
T0IR = 1;
T0CTCR = 0;
T0TC = 0;
T0PR = 0;
T0MR0 = FPCLK/250; /* 1S中断1次*/
T0MCR = 0x03; /* 匹配后产生中断*/
zyIsrSet(NVIC_TIMER0, (unsigned long)timer0Isr, PRIO_ONE); /* 设置中断并使能*/
T0TCR = 0x01; /* 启动定时器*/
}
/***************************************************************** ****************************************
** Function name: timer1Init
** Descriptions: 定时器1初始化函数
** input parameters: 无
** output parameters: 无
** Returned value: 测频计数器
***************************************************************** ****************************************/
void timer1Init (void)
{
PCONP |= 1 << 2;
/* 打开定时器1的功率控制*/
T1CTCR = 0x02|(0x00<<2);
T1TC = 0;
T1TCR = 0x01;
/* 启动定时器*/
}
/***************************************************************** ****************************************
** Function name: timer3Init
** Descriptions: 定时器3初始化程序
** input parameters: 无
** output parameters: 无
** Returned value: 定时1s,刷新屏幕,计算频率,重新给da输出送参数
***************************************************************** ****************************************/
void timer3Init (void)
{
PCONP |= 1 << 23;
T3TCR = 0x02;
T3IR = 0x01;
T3CTCR = 0;
T3TC = 0;
T3PR = 0;
T3MR0 = FPCLK; /* 1S中断1次*/
T3MCR = 0x03; /* 匹配后产生中断*/
zyIsrSet(NVIC_TIMER3, (unsigned long)timer3Isr, PRIO_TWO); /* 设置中断并使能*/
T3TCR = 0x01; /* 启动定时器*/
}
/***************************************************************** ****************************************
** Function name: main
** Descriptions: AD采集数据例程,需将JP4中的AD0.2与P0.25短接,JP2中的TXD0与P0.2,RXD与P0.3短接。
** 同时将PC机的串口线连接到开发板UART0,打开Easyarm串口调试软件,观察采样结果。
** 注意:由于AD参考电压是3.0V,若直接采用P0.25采集电压,电压不得高于3.0V。
** input parameters: 无
** output parameters: 无
** Returned value: 无
***************************************************************** ****************************************/
int main(void)
{
static INT32U ulADCbuf;
/* AD采集数据缓冲区*/
static INT32U ulADCData=0;
static INT8U i;
targetInit();
/* 初始化目标板,切勿删除*/
pinInit();
/* 引脚初始化*/