Перейти к содержанию
    

DDS на ATmega, проблемы с прошивкой

Приветствую уважаемое сообщество.

Решил соорудить функциональный генератор тупо повторив один из проектов на ATmega16

https://tehnoobzor.com/schemes/measurements/2830-shema-dds-generatora-signalov.html#programmnoe-obespechenie

с исходными кодами на WinAVR-GCC. Но mega16 не оказалось в наличии, решил использовать mega8535.

После компиляции исходника и прошивки 8535 в Atmel Studio 7 генератор почти заработал - вместо синусоиды

формирует ее четвертинку. В тексте проекта написано

Цитата

Таблица форм DDS-сигналов размещена во флэш памяти МК, адрес которой начинается с 0xXX00. Эти секции определены в makefile, в соответствующих местах в памяти:
 

#Define sections where to store signal tables
LDFLAGS += -Wl,-section-start=.MySection1=0x3A00
LDFLAGS += -Wl,-section-start=.MySection2=0x3B00
LDFLAGS += -Wl,-section-start=.MySection3=0x3C00
LDFLAGS += -Wl,-section-start=.MySection4=0x3D00
LDFLAGS += -Wl,-section-start=.MySection5=0x3E00
LDFLAGS += -Wl,-section-start=.MySection6=0x3F00

Что мне делать? Вставил этот кусок в makefile, не помогло.

Спойлер

// 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
 */


// 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
//
//*****************************************************************************

# define    F_CPU 16000000UL
#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
//MySection1=0x3a00;
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 Timer0_init()
{
    DDRB|= 1<<PB3;
    TCCR0=0x7b;
    OCR0=127;
}
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
Timer0_init();
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;
}

 

Screenshot_37.png

Изменено пользователем domowoj

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Поменяй тройки на единички в адресах секций и будет счастье. Ничего самому, кроме названия мк в Makefile, вставлять не надо. Достаточно сделать 2 вещи: 

# MCU name
MCU = atmega8535

и

#Define sections where to store signal tables
LDFLAGS += -Wl,-section-start=.MySection1=0x1A00
LDFLAGS += -Wl,-section-start=.MySection2=0x1B00
LDFLAGS += -Wl,-section-start=.MySection3=0x1C00
LDFLAGS += -Wl,-section-start=.MySection4=0x1D00
LDFLAGS += -Wl,-section-start=.MySection5=0x1E00
LDFLAGS += -Wl,-section-start=.MySection6=0x1F00 

На выходе получим:

AVR Memory Usage
----------------
Device: atmega8535

Program:    6254 bytes (76.3% Full)
(.text + .data + .bootloader)

Data:         91 bytes (17.8% Full)
(.data + .bss + .noinit)

Это без учёта секций кода с таблицами.

 

2020-02-08_11-22-09.png

Изменено пользователем uni

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если в Makefile добавить несколько дополнительных опций компилятора и компоновщика (в соответствующие места по аналогии), то можно сэкономить 450 байт памяти программ.

# Внимание. Те функции, которые не вызываются, не включаются в объектный файл.
CFLAGS += -ffunction-sections
CFLAGS += -fdata-sections
# Внимание. Те функции, которые не вызываются, не включаются в объектный файл.
CPPFLAGS += -ffunction-sections
CPPFLAGS += -fdata-sections
# Внимание. Те функции, которые не вызываются, не включаются в объектный файл.
LDFLAGS += -Wl,-gc-sections

Результат для компилятора 5.4.0:

avr-gcc.exe (GCC) 5.4.0
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
AVR Memory Usage
----------------
Device: atmega8535

Program:    5802 bytes (70.8% Full)
(.text + .data + .bootloader)

Data:         91 bytes (17.8% Full)
(.data + .bss + .noinit)

 

Изменено пользователем uni
Ошибка в числе байт

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Моя возня в этой тебе вот тут Soft-NCO-DDS-на-микроконтроллере

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В 08.02.2020 в 13:26, uni сказал:

Поменяй тройки на единички в адресах секций и будет счастье. Ничего самому, кроме названия мк в Makefile, вставлять не надо. Достаточно сделать 2 вещи: 


# MCU name
MCU = atmega8535

и


#Define sections where to store signal tables
LDFLAGS += -Wl,-section-start=.MySection1=0x1A00
LDFLAGS += -Wl,-section-start=.MySection2=0x1B00
LDFLAGS += -Wl,-section-start=.MySection3=0x1C00
LDFLAGS += -Wl,-section-start=.MySection4=0x1D00
LDFLAGS += -Wl,-section-start=.MySection5=0x1E00
LDFLAGS += -Wl,-section-start=.MySection6=0x1F00 

А куда это вставить-то?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В оригинальной статье есть ссылка на архив. В архиве есть другой архив: Последняя версия ПО. В этом архиве есть папка Firmware, в которой находится Makefile. Эти опции являются ключами компоновщика, задающими адреса для секций таблиц с отсчётами формируемых сигналов. Ключи эти уже находятся в этом Makefile и вставлять их отдельно не надо. Нужно открыть файл в текстовом редакторе, поиском найти список этих ключей и заменить значения адресов указанным образом (начальные тройки поменять на единички). После этого нужно пересобрать проект, не забыв также заменить тип мк.
Когда мы делаем такую замену, мы размещаем эти таблицы в конце памяти программ. Адреса для ATmega16 нам не подходят, т.к. они находятся выше 8К, доступных для ATmega8535. Если оставить цифры как есть и получить hex-файл, то мне трудно предсказать что будет, если попытаться этот файл прошить в мк, имеющий в 2 раза меньше флеш памяти. Удивительно ещё, что не было ошибки на каком-то из этапов.

Изменено пользователем uni

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я привык использовать самостоятельную сборку из консоли при помощи make утилиты и не понял, почему же не получается повторить мои действия. В Atmel Studio 7 это делается немного по-другому, если в настройках не выбирать внешний Makefile. Я приложил несколько окон настроек среды разработки.

1. Необходимо добавить значение символа F_CPU, который обычно используется при сборке исходников.
2. Добавить записи в Memory Settings настроек Linker'а. Тут следует иметь в виду, что числа, которые я указывал выше нужно поделить пополам, как на картинке.

Я создал новое решение, добавил файлы в проект, изменил несколько настроек и собрал проект. Результат сборки:

Program Memory Usage 	:	5596 bytes   68,3 % Full
Data Memory Usage 		:	91 bytes   17,8 % Full

Полученный hex-файл проверил в симуляторе Proteus'а. Работает также.

 

2020-02-10_20-44-21.png

2020-02-10_20-45-11.png

Изменено пользователем uni

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...