基于LPC2138的简易信号发生器

[摘要]
  本设计主要研究和设计基于ARM(LPC2138)嵌入式系统的多功能简易数字信号发生器,采用数值计算合成和D/A转换模块来完成,可产生输出频率及幅度可调的正弦波、方波、三角波及阶梯波,具有信号频率、波形、幅度变化容易,硬件简单可靠等特点。

一、要求

  1. 能产生正弦波、方波、三角波、阶梯波。
  2. 按键实现波形的切换。
  3. 频率、幅值可调。

二、方案

0.系统框图

按键
芯片LPC2138
D/A转换
输出至示波器显示

1.信号产生
  在LPC21XX系列中,LPC213x和LPC214x的芯片拥有10位数模转换器,即DAC。可以实现将数字信号转为模拟信号输出。

管脚名称 类型 管脚描述
AOUT 输出 模拟输出。当 DACR 写入一个新值选择好设定时间后,该管脚上的电压(相对 VssA)为 VALUE /1024*VREF
VREF 参考电压 参考电压。该管脚为 D/A 转换器提供一个参考电压。
VDDA,VSSA 电源 模拟电源和地。它们分别与标称为 VDD 和 VSSD 的电压相同,但为了降低噪声和出错几率,两者应当隔离。

  DAC 寄存器(DACR – 0xE006C000)是一个可读写寄存器,它包含用于D/A转换的数值和一个用来调节转换性能和功率两者之间的关系的位。寄存器的Bit[5:0]保留,供给更高性能的D/A转换器将来使用。

符号 描述 复位值
5:0 保留 NA
15:6 VALUE 0 ~ 1023 当该字段写入一个新值选择好设定时间后,AOUT 管脚上的电压()相对 VssA)为 VALUE /1024*VREF 0
16 BIAS 0\1 DAC 的设定时间最大为 1us,最大电流为 700uA。\ DAC 的设定时间为 2.5us,最大电流为 350uA。 0
31:17 保留 NA

  VALUE 值的设定。该 D/A 模块是 10 位 D/A 转换模块,因而VALUE 字段每单位对应的电压值为:VREF/1024(2^10 = 1024)。因而,如果往 VALUE 字段写入的值为 VALUE,
则转换稳定后得到的电压值 VDA为:
     VDA= V A L U E 1024 \frac{VALUE}{1024} × \times VREF
  很容易得到,当要得到稳定的电压 VDA的时候,往VALUE 字段写入的值 VALUE 为:
     VALUE= V D A V R E F \frac{V_{DA}}{V_{REF}} × \times 1024

如下程序是一个输出三角波的程序:

#include "LPC213x.h"
int main(void){
   PINSEL1 = (PINSEL1&(~(0x03<<18))) | (0x02<<18); // P0.25 连接Aout 
   while(1) {
   		uint16 j,i=0;
    	for(i=0;i<1024;i++) 
    	{
    		DACR=(i<<6)|(1<<16); //设定DAC的时间为2.5US
    		for (j=0; j<0x20; j++); // 等待D/A 转换完成
    	}
    	for(i=1023;i>0;i--)
    	{
    		DACR=(i<<6)|(1<<16);
    		for (j=0; j<0x20; j++);
    	}
    }
}

2.波形产生
  在设计中我们选择先定义一个1024位的数组来存放输出波形时所需要的点。再根据时间依次输出数组中的值即可产生所需的波形。
(1)三角波
 我们可以将一个周期的三角波看做两条直线,一条从0上升到1024、一条从1024降至0。按照如此方法我们可以先得到三角波所需要的值。

for(i=0;i<512;i++)
{
	table[i]=i*2;
}
for(i=512;i<1024;i++)
{
	table[i]=(1023-i)*2;
} 

(2)方波
 将一个周期的波形分为两个段,一段是值为1023的直线、一段是值为0的直线。

for(i=0;i<1024;i++)
{
 	if(i<512)
 		table[i]=1023;
 	else
 		table[i]=0;
}

(3) 阶梯波
 阶梯波的输出方式我感觉自己取巧了一下,我先定义了一个从0到1023的自增数i,每128次自增后赋值给m,放入数组中。整段函数的意思就是在数组放入了128个0、128个128、128个256…

uint16 m=0;
for(i=0;i<1024;i++)
{
if(i%128==0)
	m=i;
table[i]=m;
}

(4)正弦波
 我在网上找到了一种写法是自定义数组的值:

uint16 table[]=
{
0x200,0x203,0x206,0x209,0x20c,0x20f,0x212,0x215,0x219,0x21c,0x21f,0x222,
0x225,0x228,0x22b,0x22f,0x232,0x235,0x238,0x23b,0x23e,0x241,0x244,0x247,
0x24b,0x24e,0x251,0x254,0x257,0x25a,0x25d,0x260,0x263,0x266,0x269,0x26d,
0x270,0x273,0x276,0x279,0x27c,0x27f,0x282,0x285,0x288,0x28b,0x28e,0x291,
0x294,0x297,0x29a,0x29d,0x2a0,0x2a3,0x2a6,0x2a9,0x2ac,0x2af,0x2b2,0x2b5,
0x2b8,0x2bb,0x2be,0x2c0,0x2c3,0x2c6,0x2c9,0x2cc,0x2cf,0x2d2,0x2d5,0x2d7,
0x2da,0x2dd,0x2e0,0x2e3,0x2e6,0x2e8,0x2eb,0x2ee,0x2f1,0x2f4,0x2f6,0x2f9,
0x2fc,0x2fe,0x301,0x304,0x307,0x309,0x30c,0x30f,0x311,0x314,0x317,0x319,
0x31c,0x31e,0x321,0x324,0x326,0x329,0x32b,0x32e,0x330,0x333,0x335,0x338,
0x33a,0x33d,0x33f,0x342,0x344,0x347,0x349,0x34b,0x34e,0x350,0x353,0x355,
0x357,0x35a,0x35c,0x35e,0x360,0x363,0x365,0x367,0x369,0x36c,0x36e,0x370,
0x372,0x374,0x376,0x379,0x37b,0x37d,0x37f,0x381,0x383,0x385,0x387,0x389,
0x38b,0x38d,0x38f,0x391,0x393,0x395,0x397,0x399,0x39b,0x39c,0x39e,0x3a0,
0x3a2,0x3a4,0x3a6,0x3a7,0x3a9,0x3ab,0x3ad,0x3ae,0x3b0,0x3b2,0x3b3,0x3b5,
0x3b7,0x3b8,0x3ba,0x3bb,0x3bd,0x3be,0x3c0,0x3c1,0x3c3,0x3c4,0x3c6,0x3c7,
0x3c9,0x3ca,0x3cb,0x3cd,0x3ce,0x3d0,0x3d1,0x3d2,0x3d3,0x3d5,0x3d6,0x3d7,
0x3d8,0x3da,0x3db,0x3dc,0x3dd,0x3de,0x3df,0x3e0,0x3e1,0x3e3,0x3e4,0x3e5,
0x3e6,0x3e7,0x3e7,0x3e8,0x3e9,0x3ea,0x3eb,0x3ec,0x3ed,0x3ee,0x3ef,0x3ef,
0x3f0,0x3f1,0x3f2,0x3f2,0x3f3,0x3f4,0x3f4,0x3f5,0x3f6,0x3f6,0x3f7,0x3f7,
0x3f8,0x3f8,0x3f9,0x3f9,0x3fa,0x3fa,0x3fb,0x3fb,0x3fc,0x3fc,0x3fc,0x3fd,
0x3fd,0x3fd,0x3fe,0x3fe,0x3fe,0x3fe,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,
0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,0x3ff,
0x3ff,0x3ff,0x3ff,0x3fe,0x3fe,0x3fe,0x3fe,0x3fd,0x3fd,0x3fd,0x3fc,0x3fc,
0x3fc,0x3fb,0x3fb,0x3fa,0x3fa,0x3fa,0x3f9,0x3f9,0x3f8,0x3f7,0x3f7,0x3f6,
0x3f6,0x3f5,0x3f4,0x3f4,0x3f3,0x3f2,0x3f2,0x3f1,0x3f0,0x3f0,0x3ef,0x3ee,
0x3ed,0x3ec,0x3eb,0x3ea,0x3ea,0x3e9,0x3e8,0x3e7,0x3e6,0x3e5,0x3e4,0x3e3,
0x3e2,0x3e1,0x3e0,0x3de,0x3dd,0x3dc,0x3db,0x3da,0x3d9,0x3d8,0x3d6,0x3d5,
0x3d4,0x3d3,0x3d1,0x3d0,0x3cf,0x3cd,0x3cc,0x3ca,0x3c9,0x3c8,0x3c6,0x3c5,
0x3c3,0x3c2,0x3c0,0x3bf,0x3bd,0x3bc,0x3ba,0x3b9,0x3b7,0x3b5,0x3b4,0x3b2,
0x3b0,0x3af,0x3ad,0x3ab,0x3aa,0x3a8,0x3a6,0x3a4,0x3a2,0x3a1,0x39f,0x39d,
0x39b,0x399,0x397,0x395,0x393,0x392,0x390,0x38e,0x38c,0x38a,0x388,0x386,
0x384,0x382,0x37f,0x37d,0x37b,0x379,0x377,0x375,0x373,0x371,0x36e,0x36c,
0x36a,0x368,0x366,0x363,0x361,0x35f,0x35c,0x35a,0x358,0x355,0x353,0x351,
0x34e,0x34c,0x34a,0x347,0x345,0x342,0x340,0x33d,0x33b,0x339,0x336,0x334,
0x331,0x32e,0x32c,0x329,0x327,0x324,0x322,0x31f,0x31d,0x31a,0x317,0x315,
0x312,0x30f,0x30d,0x30a,0x307,0x305,0x302,0x2ff,0x2fc,0x2fa,0x2f7,0x2f4,
0x2f1,0x2ef,0x2ec,0x2e9,0x2e6,0x2e4,0x2e1,0x2de,0x2db,0x2d8,0x2d5,0x2d2,
0x2d0,0x2cd,0x2ca,0x2c7,0x2c4,0x2c1,0x2be,0x2bb,0x2b8,0x2b6,0x2b3,0x2b0,
0x2ad,0x2aa,0x2a7,0x2a4,0x2a1,0x29e,0x29b,0x298,0x295,0x292,0x28f,0x28c,
0x289,0x286,0x283,0x280,0x27d,0x27a,0x277,0x273,0x270,0x26d,0x26a,0x267,
0x264,0x261,0x25e,0x25b,0x258,0x255,0x252,0x24e,0x24b,0x248,0x245,0x242,
0x23f,0x23c,0x239,0x236,0x232,0x22f,0x22c,0x229,0x226,0x223,0x220,0x21d,
0x219,0x216,0x213,0x210,0x20d,0x20a,0x207,0x203,0x200,0x1fd,0x1fa,0x1f7,
0x1f4,0x1f1,0x1ed,0x1ea,0x1e7,0x1e4,0x1e1,0x1de,0x1db,0x1d8,0x1d4,0x1d1,
0x1ce,0x1cb,0x1c8,0x1c5,0x1c2,0x1bf,0x1bb,0x1b8,0x1b5,0x1b2,0x1af,0x1ac,
0x1a9,0x1a6,0x1a3,0x1a0,0x19c,0x199,0x196,0x193,0x190,0x18d,0x18a,0x187,
0x184,0x181,0x17e,0x17b,0x178,0x175,0x172,0x16f,0x16c,0x169,0x166,0x163,
0x160,0x15d,0x15a,0x157,0x154,0x151,0x14e,0x14b,0x148,0x145,0x142,0x13f,
0x13c,0x13a,0x137,0x134,0x131,0x12e,0x12b,0x128,0x125,0x123,0x120,0x11d,
0x11a,0x117,0x115,0x112,0x10f,0x10c,0x109,0x107,0x104,0x101,0xff,0xfc,0xf9,
0xf6,0xf4,0xf1,0xee,0xec,0xe9,0xe6,0xe4,0xe1,0xdf,0xdc,0xd9,0xd7,0xd4,0xd2,
0xcf,0xcd,0xca,0xc8,0xc5,0xc3,0xc0,0xbe,0xbb,0xb9,0xb7,0xb4,0xb2,0xaf,0xad,
0xab,0xa8,0xa6,0xa4,0xa1,0x9f,0x9d,0x9b,0x98,0x96,0x94,0x92,0x90,0x8d,0x8b,
0x89,0x87,0x85,0x83,0x81,0x7f,0x7c,0x7a,0x78,0x76,0x74,0x72,0x70,0x6e,0x6d,
0x6b,0x69,0x67,0x65,0x63,0x61,0x5f,0x5e,0x5c,0x5a,0x58,0x56,0x55,0x53,0x51,
0x50,0x4e,0x4c,0x4b,0x49,0x47,0x46,0x44,0x43,0x41,0x3f,0x3e,0x3c,0x3b,0x3a,
0x38,0x37,0x35,0x34,0x32,0x31,0x30,0x2e,0x2d,0x2c,0x2b,0x29,0x28,0x27,0x26,
0x25,0x23,0x22,0x21,0x20,0x1f,0x1e,0x1d,0x1c,0x1b,0x1a,0x19,0x18,0x17,0x16,
0x15,0x14,0x13,0x12,0x12,0x11,0x10,0xf,0xe,0xe,0xd,0xc,0xc,0xb,0xa,0xa,0x9,
0x8,0x8,0x7,0x7,0x6,0x6,0x5,0x5,0x4,0x4,0x3,0x3,0x3,0x2,0x2,0x2,0x1,0x1,0x1,
0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x1,0x1,0x1,0x1,0x2,0x2,0x2,0x2,0x3,0x3,0x4,0x4,0x4,0x5,0x5,0x6,
0x6,0x7,0x7,0x8,0x8,0x9,0xa,0xa,0xb,0xc,0xc,0xd,0xe,0xf,0xf,0x10,0x11,0x12,
0x13,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,
0x21,0x22,0x24,0x25,0x26,0x27,0x28,0x2a,0x2b,0x2c,0x2d,0x2f,0x30,0x31,0x33,
0x34,0x36,0x37,0x38,0x3a,0x3b,0x3d,0x3e,0x40,0x41,0x43,0x44,0x46,0x48,0x49,
0x4b,0x4d,0x4e,0x50,0x52,0x53,0x55,0x57,0x59,0x5a,0x5c,0x5e,0x60,0x62,0x63,
0x65,0x67,0x69,0x6b,0x6d,0x6f,0x71,0x73,0x75,0x77,0x79,0x7b,0x7d,0x7f,0x81,
0x83,0x85,0x87,0x8a,0x8c,0x8e,0x90,0x92,0x94,0x97,0x99,0x9b,0x9d,0xa0,0xa2,
0xa4,0xa7,0xa9,0xab,0xae,0xb0,0xb2,0xb5,0xb7,0xba,0xbc,0xbe,0xc1,0xc3,0xc6,
0xc8,0xcb,0xcd,0xd0,0xd2,0xd5,0xd7,0xda,0xdd,0xdf,0xe2,0xe4,0xe7,0xea,0xec,
0xef,0xf2,0xf4,0xf7,0xfa,0xfc,0xff,0x102,0x105,0x107,0x10a,0x10d,0x110,0x112,
0x115,0x118,0x11b,0x11e,0x120,0x123,0x126,0x129,0x12c,0x12f,0x131,0x134,0x137,
0x13a,0x13d,0x140,0x143,0x146,0x149,0x14c,0x14f,0x152,0x155,0x157,0x15a,0x15d,
0x160,0x163,0x166,0x169,0x16c,0x16f,0x172,0x175,0x178,0x17b,0x17f,0x182,0x185,
0x188,0x18b,0x18e,0x191,0x194,0x197,0x19a,0x19d,0x1a0,0x1a3,0x1a6,0x1a9,0x1ad,
0x1b0,0x1b3,0x1b6,0x1b9,0x1bc,0x1bf,0x1c2,0x1c5,0x1c9,0x1cc,0x1cf,0x1d2,0x1d5,
0x1d8,0x1db,0x1de,0x1e2,0x1e5,0x1e8,0x1eb,0x1ee,0x1f1,0x1f4,0x1f8,0x1fb
};

protues仿真图为平滑的完整正弦信号
正弦波_1
另外一种是使用sin函数产生正弦波需要的点

for(i=0;i<1024;i++)  
	{
		table[i] = 512+511*sin(2*3.14159*i/1024);
	}

公式为sin(2 π \pi × \times i 1024 \frac{ i }{1024} )当i=256时有最大值为1,值太小乘以511;且DAC无法输出负数,所以加上一个整数512。

但是输出的信号不太平滑
正弦波_2

以上两种方法显然是第一种方案好一点,但是代码段有一点复杂。在把程序烧录到LPC2138芯片后,在示波器上的波形却没有太大的区别,所以选择第二种函数的方法产生正弦信号点。

3.按键设计
  采用了五个按键:一个按键控制波形切换,两个控制幅值调节,两个控制频率调节。
  
按键流程图
按键流程图
  波形切换:先通过按键改变键值的大小,再通过键值判断采取何种波形。按键可以采用按键扫描、外部中断或者定时器扫描的方式按键是否按下。判断键值时一般采用switch(key)的方式。可以在初始化时将四种波形分别放入四个数组输出时只需要选择相应的数组输出即可,或者使用一个数组,使用何种波形时就将所需的波形点放入其中,最后输出即可。我采用的是后者。

波形选择
  幅值调节:这里采取的方式是定义了一个参数h,通过按键使其在0~26间改变。
  频率调节:这里采取的方式是定义了一个参数fc,按键则使其在0~100间改变。

4.幅值调节的方法
  之前放入数组中的四种波形的最大值为1024,按照DAC的输出公式:VDA= V A L U E 1024 \frac{VALUE}{1024} × \times VREF 输出的都是幅值为3.3V的波形。将数组中的波形看做标准波形的话,可以通过减小输出值的方式改变波形幅值。

if(t>1024)	{ t=0; }	//循环为0~1023
DACR=((table[t]*h/26)<<6)|(1<<16);	//DAC的输出 6到15位为输出值,16位等于1,DAC的设定时间为2.5us,最大电流为 350uA
t++;

将输出的值分为26份,而通过按键改变h的方式则可以改变输出的值,即改变幅值。当h=26时为最大幅值3.3V。

5.频率调节的方法
  我采用的是通过定时器的方法改变波形的频率。若将定时器的输出间隔设为t,则波形的两个点之间的时间间隔则为t,整个波形的周期为1024 × \times t。所以可以实现改变频率的效果。
  定时器初始化的程序为

T0TC=0;		//定时器设置为0
T0PR=0;		//时钟不分频
T0MCR=0x03;						
T0MR0=Fpclk/100*fc/100;	//定时器的最大值为0.01s
T0TCR=0x01;	//启动定时器

在这里我将定时时间分为100份,通过改变fc的值来改变频率。

三、protues仿真

电路图为
在这里插入图片描述
仿真效果
正弦波
方波
三角波
阶梯波

其中正弦的示波器波形为
正弦波

按照之前的片段因该就可以做出所需的简易示波器,详细的keil程序和protues仿真图见:https://download.csdn.net/download/qq_41853244/10876604

猜你喜欢

转载自blog.csdn.net/qq_41853244/article/details/85240369