圣源电子制作
标题:
AVR单片机的DDS信号发生器V2.0-正弦波-方波-锯-三角形-心电图和噪音-转载自国外网站
[打印本页]
作者:
sydz
时间:
2011-11-11 23:24
标题:
AVR单片机的DDS信号发生器V2.0-正弦波-方波-锯-三角形-心电图和噪音-转载自国外网站
改进AVR DDS信号发生器是在这里。 第一AVR单片机的DDS V1.0发电机只是一个没有任何幅度控制运行的DDS算法的尝试。 这一次,我仍然想保持如普遍使用的电路元件,单面电路板上加上良好的功能来的最低计数简单的事情。
(, 下载次数: 170)
上传
点击文件名下载附件
AVR的DDS规范
AVR DDS信号发生器V2.0是基于DDS信号发生器,它使用稍加修改固件加斯帕的DDS行ASM AVR GCC的C程序算法适应。 信号发生器有两个输出 - DDS信号和高速[1 .. 8MHz的方波信号 - 以及可重温微控制器熔丝设置错误,或用于其他用途。 高速(HS)的信号是从ATMEGA16 OC1A(PD5)引脚直接输出。 DDS的输出用于其他信号所产生的所有通过的R2R电阻网络,并通过抵消LM358N和幅度调节电路调整。 偏移和幅度可以由两个电位器调节。 偏移,可调节范围+5 V .- 5V,而在幅度范围0 .. 10V。 DDS的频率范围是从0到65534Hz,足够用于测试音频电路和其他任务。
V2.0的主要AVR的DDS信号发生器的功能:
简单的电路,方便和便宜的组件;
单面印刷电路板;
框与外部的交流电源插头电源;
专用高速(HS)的信号输出至8MHz;
DDS的可变幅度和偏置信号;
DDS的信号:正弦波,方波,锯,转看到,三角形,心电图和噪音。
2 × 16 LCD菜单;
直观的5键键盘。
频率调整步骤:1,10,100,1000,10000HZ;
电后恢复最后一次配置。
在框图中,你可能会看到信号generatorV2.0的逻辑结构
(, 下载次数: 154)
上传
点击文件名下载附件
正如你可以看到设备需要几个电压:+5 V,- 12V,+12 V,GND。 - 12V和+12 V用于胶印和幅度控制。 在这种情况下,电源结构使用简单的变压器和稳压器很少。
(, 下载次数: 160)
上传
点击文件名下载附件
电源模块是一个单独的原型PCB板组装。
(, 下载次数: 154)
上传
点击文件名下载附件
如果你不想建立电源,您可以使用PC ATX电源供应器,在所有需要的电压。 您可能需要修改Molex连接器接线如下:
(, 下载次数: 152)
上传
点击文件名下载附件
LCD菜单控制
所有操作都可以被视为在LCD菜单。 菜单可控制5个按钮,液晶显示模块
(, 下载次数: 157)
上传
点击文件名下载附件
向上和向下箭头按钮可用于浏览菜单,而左,右箭头按钮用于改变频率值。 当按下中间的按钮 - 信号产生开始。 按中间的按钮再次停止信号发生器。 下面是一个完整的菜单系统,信号发生器。
重要通知,有一个单独的菜单改变频率步进。 如果您需要更改发生器频率范围宽,这是很方便。 这允许设置任何频率相对较少的按钮点击。
噪音的产生,没有频率设置。 它使用简单兰特()函数,结果连续输出DDS输出。
高速信号有4个频率可供选择:1,2,4和8MHz。
电路图和PCB
的DDS发生器(不含电源)电路原理图,非常简单容易的访问组件。 它使用了以下几个部分:
AVR单片机ATmega16单片机主频16MHz的外部晶体;
标准HD44780的基于2 × 16液晶显示模块;
R2R DAC,简单的电阻;
LM358N低功耗双运算放大器;
两个电位器;
5个按钮;
多个接头和插座。
电路图和PCB:
(, 下载次数: 219)
上传
点击文件名下载附件
单面印刷电路板:
(, 下载次数: 173)
上传
点击文件名下载附件
大会
DDS发生器组装塑料盒:
(, 下载次数: 150)
上传
点击文件名下载附件
试运行:
(, 下载次数: 159)
上传
点击文件名下载附件
AVR DDS 2.0固件
正如我刚才所说的DDS功能是修改后的加斯帕的 DDS算法。 主要修改是增加了额外的ASM线,使停止DDS生成。 在1.0版中是唯一的选择是复位设备,DDS功能检查,如果CPHA位在SPCR寄存器的设置是在外部中断服务程序(停止按钮)设置。 所以,现在的算法需要10个CPU周期,而不是9。
无效的静态内嵌Signal_OUT(CONST uint8_t uint8_t *信号,uint8_t AD2,uint8_t AD1,AD0)
{
ASM挥发(EOR R18,R18,R18 <-0“,” N T“
“EOR R19,R19,R19 <-0”的“ n T”
“1:” N T“
“添加R18,0%; 1个周期”的“ n T”
“ADC,1%R19; 1个周期”的“ n T”
“ADC%A3%2; 1个周期”的“ n T”
“防止山泥倾泻; 3个周期”的“ n T”
“%4 出,__tmp_reg__; 1个周期”,“ N T”
“SBIS 5%,2,1个周期,如果没有跳过”,“ N T
“
“RJMP 1B,2个周期。
共有10个周期“,” N T“
:
:“R”(AD0),“R”(AD1),“R”(AD2),“E”(信号),“我”(_SFR_IO_ADDR(PORTA)),“我”(_SFR_IO_ADDR(SPCR))
“R18”,“R19”
);}
DDS信号表放置在闪光路段地址与0xXX00开始。 因此,这些路段将在适当的
内存
位置的makefile定义:
#定义路段存储信号表
LDFLAGS + = - WL -节启动=. MySection1 = 0x3A00
LDFLAGS + = - WL -节启动=. MySection2 = 0x3B00
LDFLAGS + = - WL -节启动=. MySection3 = 0x3C00
LDFLAGS + = - WL -节启动=. MySection4 = 0x3D00
LDFLAGS + = - WL -节启动=. MySection5 = 0x3E00
LDFLAGS + = - WL -节启动=. MySection6 = 0x3F00
这里描述的LCD控制库。
我不想去代码讨论太深。 源代码的评论非常好,如果会有关于源代码的任何问题和建议 - 随意删除评论。
测试和讨论
我已经测试信号发生器,示波器和频率计数器。 信号看起来像所有频率的范围[1至65535Hz]预期。 振幅和偏移调节工程确定。 如果offset设置为5V,那么最大的明确信号幅度可能是5V另一5V已经用于抵消(相同的是如果偏移量为- 5V)。
下面是一些测试信号示波器屏幕上:
(, 下载次数: 153)
上传
点击文件名下载附件
正弦波信号
(, 下载次数: 155)
上传
点击文件名下载附件
方波信号
(, 下载次数: 149)
上传
点击文件名下载附件
三角形信号
(, 下载次数: 155)
上传
点击文件名下载附件
看到牙齿信号
(, 下载次数: 155)
上传
点击文件名下载附件
反向看到牙齿信号
(, 下载次数: 149)
上传
点击文件名下载附件
心电信号
(, 下载次数: 151)
上传
点击文件名下载附件
噪音
(, 下载次数: 158)
上传
点击文件名下载附件
高速1MHz的信号
作者:
sydz
时间:
2011-11-11 23:28
C程序
//*****************************************************************************
//
// File Name : 'main.c'
// Title : AVR DDS2 signal generator
// Author : Scienceprog.com - Copyright (C) 2008
// Created : 2008-03-09
// Revised : 2008-03-09
// Version : 2.0
// Target MCU : Atmel AVR series ATmega16
//
// This code is distributed under the GNU Public License
// which can be found at http://www.gnu.org/licenses/gpl.txt
//
//*****************************************************************************
#include <stdio.h>
#include <stdlib.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/eeprom.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <inttypes.h>
#include "lcd_lib.h"
//define R2R port
#define R2RPORT PORTA
#define R2RDDR DDRA
//define button port and dedicated pins
#define BPORT PORTD
#define BPIN PIND
#define BDDR DDRD
#define DOWN 0//PORTD
#define LEFT 1//PORTD
#define START 2//PORTD
#define RIGHT 3//PORTD
#define UP 4//PORTD
//Define Highs Speed (HS) signal output
#define HSDDR DDRD
#define HSPORT PORTD
#define HS 5//PD5
//define eeprom addresses
#define EEMODE 0
#define EEFREQ1 1
#define EEFREQ2 2
#define EEFREQ3 3
#define EEDUTY 4
#define EEINIT E2END
#define RESOLUTION 0.095367431640625
#define MINFREQ 0//minimum frequency
#define MAXFREQ 65534//maximum DDS frequency
#define MN_No 9// number of menu items
//function prototypes
void delay1s(void);
void Timer2_Init(void);
void Timer2_Start(void);
void Timer2_Stop(void);
void Main_Init(void);
void Menu_Update(uint8_t);
void Freq_Update(void);
void Timer1_Start(uint8_t);
void Timer1_Stop(void);
void static inline Signal_OUT(const uint8_t *, uint8_t, uint8_t, uint8_t);
//adjust LCDsendChar() function for strema
static int LCDsendstream(char c, FILE *stream);
//----set output stream to LCD-------
static FILE lcd_str = FDEV_SETUP_STREAM(LCDsendstream, NULL, _FDEV_SETUP_WRITE);
//Menu Strings in flash
const uint8_t MN000[] PROGMEM=" Sine \0";
//menu 1
const uint8_t MN100[] PROGMEM=" Square \0";
//menu 2
const uint8_t MN200[] PROGMEM=" Triangle \0";
//menu 3
const uint8_t MN300[] PROGMEM=" SawTooth \0";
//menu 4
const uint8_t MN400[] PROGMEM=" Rev SawTooth \0";
//menu 5
const uint8_t MN500[] PROGMEM=" ECG \0";
//menu 6
const uint8_t MN600[] PROGMEM=" Freq Step \0";
//menu 7
const uint8_t MN700[] PROGMEM=" Noise \0";
//menu 8
const uint8_t MN800[] PROGMEM=" High Speed \0";
//Array of pointers to menu strings stored in flash
const uint8_t *MENU[]={
MN000, //
MN100, //menu 1 string
MN200, //menu 2 string
MN300, //menu 3 string
MN400, //menu 4 string
MN500,
MN600,
MN700,
MN800
};
//various LCD strings
const uint8_t MNON[] PROGMEM="ON \0";//ON
const uint8_t MNOFF[] PROGMEM="OFF\0";//OFF
const uint8_t NA[] PROGMEM=" NA \0";//Clear freq value
const uint8_t CLR[] PROGMEM=" \0";//Clear freq value
const uint8_t MNClrfreq[] PROGMEM=" \0";//Clear freq value
const uint8_t TOEEPROM[] PROGMEM="Saving Settings\0";//saving to eeprom
const uint8_t ONEMHZ[] PROGMEM=" 1MHz \0";//saving to eeprom
const uint8_t welcomeln1[] PROGMEM="AVR SIGNAL\0";
const uint8_t RND[] PROGMEM=" Random\0";
//variables to control TDA7313
struct signal{
volatile uint8_t mode; //signal
volatile uint8_t fr1; //Frequency [0..7]
volatile uint8_t fr2; //Frequency [8..15]
volatile int8_t fr3; //Frequency [16..31]
volatile uint32_t freq; //frequency value
volatile uint8_t flag; //if "0"generator is OFF, "1" - ON
volatile uint32_t acc; //accumulator
volatile uint8_t ON;
volatile uint8_t HSfreq; //high speed frequency [1...4Mhz]
volatile uint32_t deltafreq; //frequency step value
}SG;
//define signals
const uint8_t sinewave[] __attribute__ ((section (".MySection1")))= //sine 256 values
{
0x80,0x83,0x86,0x89,0x8c,0x8f,0x92,0x95,0x98,0x9c,0x9f,0xa2,0xa5,0xa8,0xab,0xae,
0xb0,0xb3,0xb6,0xb9,0xbc,0xbf,0xc1,0xc4,0xc7,0xc9,0xcc,0xce,0xd1,0xd3,0xd5,0xd8,
0xda,0xdc,0xde,0xe0,0xe2,0xe4,0xe6,0xe8,0xea,0xec,0xed,0xef,0xf0,0xf2,0xf3,0xf5,
0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfc,0xfd,0xfe,0xfe,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xfe,0xfd,0xfc,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7,
0xf6,0xf5,0xf3,0xf2,0xf0,0xef,0xed,0xec,0xea,0xe8,0xe6,0xe4,0xe2,0xe0,0xde,0xdc,
0xda,0xd8,0xd5,0xd3,0xd1,0xce,0xcc,0xc9,0xc7,0xc4,0xc1,0xbf,0xbc,0xb9,0xb6,0xb3,
0xb0,0xae,0xab,0xa8,0xa5,0xa2,0x9f,0x9c,0x98,0x95,0x92,0x8f,0x8c,0x89,0x86,0x83,
0x80,0x7c,0x79,0x76,0x73,0x70,0x6d,0x6a,0x67,0x63,0x60,0x5d,0x5a,0x57,0x54,0x51,
0x4f,0x4c,0x49,0x46,0x43,0x40,0x3e,0x3b,0x38,0x36,0x33,0x31,0x2e,0x2c,0x2a,0x27,
0x25,0x23,0x21,0x1f,0x1d,0x1b,0x19,0x17,0x15,0x13,0x12,0x10,0x0f,0x0d,0x0c,0x0a,
0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x03,0x02,0x01,0x01,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x05,0x06,0x07,0x08,
0x09,0x0a,0x0c,0x0d,0x0f,0x10,0x12,0x13,0x15,0x17,0x19,0x1b,0x1d,0x1f,0x21,0x23,
0x25,0x27,0x2a,0x2c,0x2e,0x31,0x33,0x36,0x38,0x3b,0x3e,0x40,0x43,0x46,0x49,0x4c,
0x4f,0x51,0x54,0x57,0x5a,0x5d,0x60,0x63,0x67,0x6a,0x6d,0x70,0x73,0x76,0x79,0x7c
};
const uint8_t squarewave[] __attribute__ ((section (".MySection2")))= //square wave
{
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
};
const uint8_t sawtoothwave[] __attribute__ ((section (".MySection3")))= //sawtooth wave
{
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,
0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,
0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,
0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f,
0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,
0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,
0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,
0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,
0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf,
0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,
0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf,
0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,
0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff
};
const uint8_t rewsawtoothwave[] __attribute__ ((section (".MySection4")))= //reverse sawtooth wave
{
0xff,0xfe,0xfd,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7,0xf6,0xf5,0xf4,0xf3,0xf2,0xf1,0xf0,
0xef,0xee,0xed,0xec,0xeb,0xea,0xe9,0xe8,0xe7,0xe6,0xe5,0xe4,0xe3,0xe2,0xe1,0xe0,
0xdf,0xde,0xdd,0xdc,0xdb,0xda,0xd9,0xd8,0xd7,0xd6,0xd5,0xd4,0xd3,0xd2,0xd1,0xd0,
0xcf,0xce,0xcd,0xcc,0xcb,0xca,0xc9,0xc8,0xc7,0xc6,0xc5,0xc4,0xc3,0xc2,0xc1,0xc0,
0xbf,0xbe,0xbd,0xbc,0xbb,0xba,0xb9,0xb8,0xb7,0xb6,0xb5,0xb4,0xb3,0xb2,0xb1,0xb0,
0xaf,0xae,0xad,0xac,0xab,0xaa,0xa9,0xa8,0xa7,0xa6,0xa5,0xa4,0xa3,0xa2,0xa1,0xa0,
0x9f,0x9e,0x9d,0x9c,0x9b,0x9a,0x99,0x98,0x97,0x96,0x95,0x94,0x93,0x92,0x91,0x90,
0x8f,0x8e,0x8d,0x8c,0x8b,0x8a,0x89,0x88,0x87,0x86,0x85,0x84,0x83,0x82,0x81,0x80,
0x7f,0x7e,0x7d,0x7c,0x7b,0x7a,0x79,0x78,0x77,0x76,0x75,0x74,0x73,0x72,0x71,0x70,
0x6f,0x6e,0x6d,0x6c,0x6b,0x6a,0x69,0x68,0x67,0x66,0x65,0x64,0x63,0x62,0x61,0x60,
0x5f,0x5e,0x5d,0x5c,0x5b,0x5a,0x59,0x58,0x57,0x56,0x55,0x54,0x53,0x52,0x51,0x50,
0x4f,0x4e,0x4d,0x4c,0x4b,0x4a,0x49,0x48,0x47,0x46,0x45,0x44,0x43,0x42,0x41,0x40,
0x3f,0x3e,0x3d,0x3c,0x3b,0x3a,0x39,0x38,0x37,0x36,0x35,0x34,0x33,0x32,0x31,0x30,
0x2f,0x2e,0x2d,0x2c,0x2b,0x2a,0x29,0x28,0x27,0x26,0x25,0x24,0x23,0x22,0x21,0x20,
0x1f,0x1e,0x1d,0x1c,0x1b,0x1a,0x19,0x18,0x17,0x16,0x15,0x14,0x13,0x12,0x11,0x10,
0x0f,0x0e,0x0d,0x0c,0x0b,0x0a,0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0x00,
};
const uint8_t trianglewave[] __attribute__ ((section (".MySection5")))= //triangle wave
{
0x00,0x02,0x04,0x06,0x08,0x0a,0x0c,0x0e,0x10,0x12,0x14,0x16,0x18,0x1a,0x1c,0x1e,
0x20,0x22,0x24,0x26,0x28,0x2a,0x2c,0x2e,0x30,0x32,0x34,0x36,0x38,0x3a,0x3c,0x3e,
0x40,0x42,0x44,0x46,0x48,0x4a,0x4c,0x4e,0x50,0x52,0x54,0x56,0x58,0x5a,0x5c,0x5e,
0x60,0x62,0x64,0x66,0x68,0x6a,0x6c,0x6e,0x70,0x72,0x74,0x76,0x78,0x7a,0x7c,0x7e,
0x80,0x82,0x84,0x86,0x88,0x8a,0x8c,0x8e,0x90,0x92,0x94,0x96,0x98,0x9a,0x9c,0x9e,
0xa0,0xa2,0xa4,0xa6,0xa8,0xaa,0xac,0xae,0xb0,0xb2,0xb4,0xb6,0xb8,0xba,0xbc,0xbe,
0xc0,0xc2,0xc4,0xc6,0xc8,0xca,0xcc,0xce,0xd0,0xd2,0xd4,0xd6,0xd8,0xda,0xdc,0xde,
0xe0,0xe2,0xe4,0xe6,0xe8,0xea,0xec,0xee,0xf0,0xf2,0xf4,0xf6,0xf8,0xfa,0xfc,0xfe,
0xff,0xfd,0xfb,0xf9,0xf7,0xf5,0xf3,0xf1,0xef,0xef,0xeb,0xe9,0xe7,0xe5,0xe3,0xe1,
0xdf,0xdd,0xdb,0xd9,0xd7,0xd5,0xd3,0xd1,0xcf,0xcf,0xcb,0xc9,0xc7,0xc5,0xc3,0xc1,
0xbf,0xbd,0xbb,0xb9,0xb7,0xb5,0xb3,0xb1,0xaf,0xaf,0xab,0xa9,0xa7,0xa5,0xa3,0xa1,
0x9f,0x9d,0x9b,0x99,0x97,0x95,0x93,0x91,0x8f,0x8f,0x8b,0x89,0x87,0x85,0x83,0x81,
0x7f,0x7d,0x7b,0x79,0x77,0x75,0x73,0x71,0x6f,0x6f,0x6b,0x69,0x67,0x65,0x63,0x61,
0x5f,0x5d,0x5b,0x59,0x57,0x55,0x53,0x51,0x4f,0x4f,0x4b,0x49,0x47,0x45,0x43,0x41,
0x3f,0x3d,0x3b,0x39,0x37,0x35,0x33,0x31,0x2f,0x2f,0x2b,0x29,0x27,0x25,0x23,0x21,
0x1f,0x1d,0x1b,0x19,0x17,0x15,0x13,0x11,0x0f,0x0f,0x0b,0x09,0x07,0x05,0x03,0x01
};
const uint8_t ECG[] __attribute__ ((section (".MySection6")))= //ECG wave
{
73,74,75,75,74,73,73,73,73,72,71,69,68,67,67,67,
68,68,67,65,62,61,59,57,56,55,55,54,54,54,55,55,
55,55,55,55,54,53,51,50,49,49,52,61,77,101,132,
169,207,238,255,254,234,198,154,109,68,37,17,5,
0,1,6,13,20,28,36,45,52,57,61,64,65,66,67,68,68,
69,70,71,71,71,71,71,71,71,71,72,72,72,73,73,74,
75,75,76,77,78,79,80,81,82,83,84,86,88,91,93,96,
98,100,102,104,107,109,112,115,118,121,123,125,
126,127,127,127,127,127,126,125,124,121,119,116,
113,109,105,102,98,95,92,89,87,84,81,79,77,76,75,
74,73,72,70,69,68,67,67,67,68,68,68,69,69,69,69,
69,69,69,70,71,72,73,73,74,74,75,75,75,75,75,75,
74,74,73,73,73,73,72,72,72,71,71,71,71,71,71,71,
70,70,70,69,69,69,69,69,70,70,70,69,68,68,67,67,
67,67,66,66,66,65,65,65,65,65,65,65,65,64,64,63,
63,64,64,65,65,65,65,65,65,65,64,64,64,64,64,64,
64,64,65,65,65,66,67,68,69,71,72,73
};
//array of pointers to signal tables
const uint8_t *SIGNALS[] ={
sinewave,
squarewave,
trianglewave,
sawtoothwave,
rewsawtoothwave,
ECG
};
//adjust LCD stream fuinction to use with printf()
static int LCDsendstream(char c , FILE *stream)
{
LCDsendChar(c);
return 0;
}
//delay 1s
void delay1s(void)
{
uint8_t i;
for(i=0;i<100;i++)
{
_delay_ms(10);
}
}
//initialize Timer2 (used for button reading)
void Timer2_Init(void)
{
TCNT2=0x00;
sei();
}
//start timer2
void Timer2_Start(void)
{
TCCR2|=(1<<CS22)|(1<<CS21); //prescaller 256 ~122 interrupts/s
TIMSK|=(1<<TOV2);//Enable Timer0 Overflow interrupts
}
//stop timer 2
void Timer2_Stop(void)
{
TCCR0&=~((1<<CS22)|(1<<CS21)); //Stop timer0
TIMSK&=~(1<<TOV2);//Disable Timer0 Overflow interrupts
}
//Initial menu
//show initial signal and frequency
//generator is off
void Menu_Update(uint8_t on)
{
LCDclr();
CopyStringtoLCD(MENU[(SG.mode)], 0, 0 );
LCDGotoXY(0, 1);
if (SG.mode==6)
{
CopyStringtoLCD(CLR, 0, 1 );
LCDGotoXY(0, 1);
printf(" %5uHz", (uint16_t)SG.deltafreq);
}
if (SG.mode==7)
{
CopyStringtoLCD(CLR, 0, 1 );
CopyStringtoLCD(RND, 0, 1 );
}
if (SG.mode==8)
{
CopyStringtoLCD(CLR, 0, 1 );
LCDGotoXY(0, 1);
printf(" %5uMHz", SG.HSfreq);
}
if((SG.mode==0)||(SG.mode==1)||(SG.mode==2)||(SG.mode==3)||(SG.mode==4)||(SG.mode==5))
{
CopyStringtoLCD(CLR, 0, 1 );
LCDGotoXY(0, 1);
printf(" %5uHz", (uint16_t)SG.freq);
}
if (SG.mode!=6)
{
if(on==1)
CopyStringtoLCD(MNON, 13, 1 );
else
CopyStringtoLCD(MNOFF, 13, 1 );
}
}
//update frequency value on LCD menu - more smooth display
void Freq_Update(void)
{
if (SG.mode==6)
{
LCDGotoXY(0, 1);
printf(" %5uHz", (uint16_t)SG.deltafreq);
}
if (SG.mode==8)
{
//if HS signal
LCDGotoXY(0, 1);
printf(" %5uMHz", SG.HSfreq);
}
if((SG.mode==0)||(SG.mode==1)||(SG.mode==2)||(SG.mode==3)||(SG.mode==4)||(SG.mode==5))
{
LCDGotoXY(0, 1);
printf(" %5uHz", (uint16_t)SG.freq);
}
}
//External interrupt0 service routine
//used to stop DDS depending on active menu
//any generator is stopped by setting flag value to 0
//DDs generator which is inline ASM is stopped by setting
//CPHA bit in SPCR register
ISR(INT0_vect)
{
SG.flag=0;//set flag to stop generator
SPCR|=(1<<CPHA);//using CPHA bit as stop mark
//CopyStringtoLCD(MNOFF, 13, 1 );
SG.ON=0;//set off in LCD menu
loop_until_bit_is_set(BPIN, START);//wait for button release
}
//timer overflow interrupt service tourine
//checks all button status and if button is pressed
//value is updated
ISR(TIMER2_OVF_vect)
{
if (bit_is_clear(BPIN, UP))
//Button UP increments value which selects previous signal mode
//if first mode is reached - jumps to last
{
if (SG.mode==0)
{
SG.mode=MN_No-1;
}
else
{
SG.mode--;
}
//Display menu item
Menu_Update(SG.ON);
loop_until_bit_is_set(BPIN, UP);
}
if (bit_is_clear(BPIN, DOWN))
//Button Down decrements value which selects next signal mode
//if last mode is reached - jumps to first
{
if (SG.mode<(MN_No-1))
{
SG.mode++;
}
else
{
SG.mode=0;
}
//Display menu item
Menu_Update(SG.ON);
loop_until_bit_is_set(BPIN, DOWN);
}
if (bit_is_clear(BPIN, RIGHT))
//frequency increment
{
if(SG.mode==6)
{
if(SG.deltafreq==10000)
SG.deltafreq=1;
else
SG.deltafreq=(SG.deltafreq*10);
Freq_Update();
loop_until_bit_is_set(BPIN, RIGHT);
}
if (SG.mode==8)
{
//ifhigh speed signal
if(SG.HSfreq==8)
SG.HSfreq=1;
else
SG.HSfreq=(SG.HSfreq<<1);
Freq_Update();
loop_until_bit_is_set(BPIN, RIGHT);
}
if((SG.mode==0)||(SG.mode==1)||(SG.mode==2)||(SG.mode==3)||(SG.mode==4)||(SG.mode==5))
{
if ((0xFFFF-SG.freq)>=SG.deltafreq)
SG.freq+=SG.deltafreq;
Freq_Update();
uint8_t ii=0;
//press button and wait for long press (~0.5s)
do{
_delay_ms(2);
ii++;
}while((bit_is_clear(BPIN, RIGHT))&&(ii<=250));//wait for button release
if(ii>=250)
{
do{
if ((0xFFFF-SG.freq)>=SG.deltafreq)
SG.freq+=SG.deltafreq;
Freq_Update();
}while(bit_is_clear(BPIN, RIGHT));//wait for button release
}
}
}
if (bit_is_clear(BPIN, LEFT))
//frequency decrement
{
if(SG.mode==6)
{
if(SG.deltafreq==1)
SG.deltafreq=10000;
else
SG.deltafreq=(SG.deltafreq/10);
Freq_Update();
loop_until_bit_is_set(BPIN, LEFT);
}
if (SG.mode==8)
{
//ifhigh speed signal
if(SG.HSfreq==1)
SG.HSfreq=8;
else
SG.HSfreq=(SG.HSfreq>>1);
Freq_Update();
loop_until_bit_is_set(BPIN, LEFT);
}
if ((SG.mode==0)||(SG.mode==1)||(SG.mode==2)||(SG.mode==3)||(SG.mode==4)||(SG.mode==5))
{
if (SG.freq>=SG.deltafreq)
SG.freq-=SG.deltafreq;
Freq_Update();
uint8_t ii=0;
//press button and wait for long press (~0.5s)
do{
_delay_ms(2);
ii++;
}while((bit_is_clear(BPIN, LEFT))&&(ii<=250));//wait for button release
if(ii>=250)
{
do{
if (SG.freq>=SG.deltafreq)
SG.freq-=SG.deltafreq;
Freq_Update();
}while(bit_is_clear(BPIN, LEFT));//wait for button release
}
}
}
if (bit_is_clear(BPIN, START))
{
if(SG.mode!=6)
{
//saving last configuration
SG.fr1=(uint8_t)(SG.freq);
SG.fr2=(uint8_t)(SG.freq>>8);
SG.fr3=(uint8_t)(SG.freq>>16);
if (eeprom_read_byte((uint8_t*)EEMODE)!=SG.mode) eeprom_write_byte((uint8_t*)EEMODE,SG.mode);
if (eeprom_read_byte((uint8_t*)EEFREQ1)!=SG.fr1) eeprom_write_byte((uint8_t*)EEFREQ1,SG.fr1);
if (eeprom_read_byte((uint8_t*)EEFREQ2)!=SG.fr2) eeprom_write_byte((uint8_t*)EEFREQ2,SG.fr2);
if (eeprom_read_byte((uint8_t*)EEFREQ3)!=SG.fr3) eeprom_write_byte((uint8_t*)EEFREQ3,SG.fr3);
//Calculate frequency value from restored EEPROM values
SG.freq=(((uint32_t)(SG.fr3)<<16)|((uint32_t)(SG.fr2)<<8)|((uint32_t)(SG.fr1)));
//calculate accumulator value
SG.acc=SG.freq/RESOLUTION;
SG.flag=1;//set flag to start generator
SG.ON=1;//set ON on LCD menu
SPCR&=~(1<<CPHA);//clear CPHA bit in SPCR register to allow DDS
//Stop timer2 - menu inactive
Timer2_Stop();
//display ON on LCD
Menu_Update(SG.ON);
}
loop_until_bit_is_set(BPIN, START);//wait for button release
}
}
/*DDS signal generation function
Original idea is taken from
http://www.myplace.nu/avr/minidds/index.htm
small modification is made - added additional command which
checks if CPHA bit is set in SPCR register if yes - exit function
*/
void static inline Signal_OUT(const uint8_t *signal, uint8_t ad2, uint8_t ad1, uint8_t ad0)
{
asm volatile( "eor r18, r18 ;r18<-0" "\n\t"
"eor r19, r19 ;r19<-0" "\n\t"
"1:" "\n\t"
"add r18, %0 ;1 cycle" "\n\t"
"adc r19, %1 ;1 cycle" "\n\t"
"adc %A3, %2 ;1 cycle" "\n\t"
"lpm ;3 cycles" "\n\t"
"out %4, __tmp_reg__ ;1 cycle" "\n\t"
"sbis %5, 2 ;1 cycle if no skip" "\n\t"
"rjmp 1b ;2 cycles. Total 10 cycles" "\n\t"
:
:"r" (ad0),"r" (ad1),"r" (ad2),"e" (signal),"I" (_SFR_IO_ADDR(PORTA)), "I" (_SFR_IO_ADDR(SPCR))
:"r18", "r19"
);
}
void Timer1_Start(uint8_t FMHz)
{
switch(FMHz){
case 1:
//start high speed (1MHz) signal
OCR1A=7;
break;
case 2:
OCR1A=3;//2MHz
break;
case 4:
OCR1A=1;//4MHz
break;
case 8:
OCR1A=0;//8MHz
break;
default:
OCR1A=7;//defauls 1MHz
break;}
//Output compare toggles OC1A pin
TCCR1A=0x40;
//start timer without prescaler
TCCR1B=0b00001001;
}
void Timer1_Stop(void)
{
TCCR1B=0x00;//timer off
}
//main init function
void Main_Init(void)
{
//stderr = &lcd_str;
stdout = &lcd_str;
//--------init LCD----------
LCDinit();
LCDclr();
LCDcursorOFF();
//-------EEPROM initial values----------
if (eeprom_read_byte((uint8_t*)EEINIT)!='T')
{
eeprom_write_byte((uint8_t*)EEMODE,0x00);//initial mode 0 ?OUT~~~~;
eeprom_write_byte((uint8_t*)EEFREQ1,0xE8);//initial frequency 1kHz
eeprom_write_byte((uint8_t*)EEFREQ2,0x03);
eeprom_write_byte((uint8_t*)EEFREQ3,0x00);
eeprom_write_byte((uint8_t*)EEINIT,'T');//marks once that eeprom init is done
//once this procedure is held, no more initialization is performed
}
//------restore last saved values from EEPROM------
SG.mode=eeprom_read_byte((uint8_t*)EEMODE);
SG.fr1=eeprom_read_byte((uint8_t*)EEFREQ1);
SG.fr2=eeprom_read_byte((uint8_t*)EEFREQ2);
SG.fr3=eeprom_read_byte((uint8_t*)EEFREQ3);
SG.freq=(((uint32_t)(SG.fr3)<<16)|((uint32_t)(SG.fr2)<<8)|((uint32_t)(SG.fr1)));
SG.acc=SG.freq/RESOLUTION;
SG.flag=0;
//default 1MHz HS signal freq
SG.HSfreq=1;
SG.deltafreq=100;
//------------init DDS output-----------
R2RPORT=0x00;//set initial zero values
R2RDDR=0xFF;//set A port as output
//-------------set ports pins for buttons----------
BDDR&=~(_BV(START)|_BV(UP)|_BV(DOWN)|_BV(RIGHT)|_BV(LEFT));
BPORT|=(_BV(START)|_BV(UP)|_BV(DOWN)|_BV(RIGHT)|_BV(LEFT));
//---------set ports pins for HS output---------
HSDDR|=_BV(HS);//configure as output
//-----------Menu init--------------
SG.ON=0;//default signal is off
Menu_Update(SG.ON);
//-----------Timer Init-------------
Timer2_Init();
//Start Timer with overflow interrupts
Timer2_Start();
}
int main(void)
{
//Initialize
Main_Init();
while(1)//infinite loop
{
if (SG.flag==1)
{
GICR|=(1<<INT0);//set external interrupt to enable stop
if (SG.mode==7)
{
//Noise
do
{
R2RPORT=rand();
}while(SG.flag==1);
//set signal level to 0
R2RPORT=0x00;
//display generator OFF
Menu_Update(SG.ON);
//stop external interrupt
GICR&=~(1<<INT0);
//start timer menu active
Timer2_Start();
}
/* else if (SG.mode==6)
{
//freq step
while((SG.flag==1))
{
//not implemented
CopyStringtoLCD(NA, 0, 1 );
}
//set signal level to 0
R2RPORT=0x00;
//display generator OFF
Menu_Update(SG.ON);
GICR&=~(1<<INT0);//|(1<<INT1);//stop external interrupt
//start timer menu active
Timer2_Start();
}*/
else if (SG.mode==8)
{
//High speed signal
Timer1_Start(SG.HSfreq);
while((SG.flag==1))
{
//not implemented
CopyStringtoLCD(MNON, 13, 1 );
}
Timer1_Stop();//timer off
//set HS pin to LOW
HSPORT&=~(1<<HS);
//display generator OFF
Menu_Update(SG.ON);
GICR&=~(1<<INT0);//|(1<<INT1);//stop external interrupt
//start timer menu active
Timer2_Start();
}
else
{
//start DDS
Signal_OUT(SIGNALS[SG.mode],
(uint8_t)((uint32_t)SG.acc>>16),
(uint8_t)((uint32_t)SG.acc>>8),
(uint8_t)SG.acc);
//set signal level to 0
R2RPORT=0x00;
//display generator OFF
Menu_Update(SG.ON);
GICR&=~(1<<INT0);//|(1<<INT1);//stop external interrupt
//start timer menu active
Timer2_Start();
}
}
}
return 0;
}
复制代码
PCB图
(, 下载次数: 164)
上传
点击文件名下载附件
本人亲测,仿真
(, 下载次数: 159)
上传
点击文件名下载附件
(, 下载次数: 154)
上传
点击文件名下载附件
(, 下载次数: 161)
上传
点击文件名下载附件
(, 下载次数: 159)
上传
点击文件名下载附件
(, 下载次数: 159)
上传
点击文件名下载附件
(, 下载次数: 163)
上传
点击文件名下载附件
作者:
sydz
时间:
2011-11-11 23:28
下载:
(, 下载次数: 134)
上传
点击文件名下载附件
(, 下载次数: 115)
上传
点击文件名下载附件
(, 下载次数: 157)
上传
点击文件名下载附件
作者:
墨齐
时间:
2012-5-3 12:07
原理图PCB图打不开,楼主能提供个清晰的原理图么
作者:
sydz
时间:
2012-5-3 12:13
墨齐 发表于 2012-5-3 12:07
原理图PCB图打不开,楼主能提供个清晰的原理图么
点击可以直接 放大~~~
(, 下载次数: 173)
上传
点击文件名下载附件
作者:
墨齐
时间:
2012-5-3 12:21
isp reset 这两个是什么?
作者:
sydz
时间:
2012-5-3 12:30
墨齐 发表于 2012-5-3 12:21
isp reset 这两个是什么?
现在口 和 复位开关
作者:
sx3339241
时间:
2012-5-4 17:13
很强大的功能!楼主是那里找的这么强劲的资料!
作者:
wlsy008
时间:
2012-6-19 21:38
楼主,熔丝怎么设置呀,这个关键
作者:
wlsy008
时间:
2012-6-19 23:21
楼主,熔丝怎么设置的呀,这个是关键
作者:
wanwenzhang
时间:
2015-10-15 15:35
楼主发帖辛苦了,谢谢分享!!!!!!!!!
作者:
漂泊
时间:
2015-12-10 09:47
资料很详细改天仿一个
作者:
mirage
时间:
2018-3-8 21:45
资料很详细
欢迎光临 圣源电子制作 (https://bbs.syyyd.com/)
Powered by Discuz! X3.4