domowoj 0 7 февраля, 2020 Опубликовано 7 февраля, 2020 (изменено) · Жалоба Приветствую уважаемое сообщество. Решил соорудить функциональный генератор тупо повторив один из проектов на 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 fromhttp://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; } Изменено 7 февраля, 2020 пользователем domowoj Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
uni 6 8 февраля, 2020 Опубликовано 8 февраля, 2020 (изменено) · Жалоба Поменяй тройки на единички в адресах секций и будет счастье. Ничего самому, кроме названия мк в 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) Это без учёта секций кода с таблицами. Изменено 8 февраля, 2020 пользователем uni Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
uni 6 8 февраля, 2020 Опубликовано 8 февраля, 2020 (изменено) · Жалоба Если в 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) Изменено 8 февраля, 2020 пользователем uni Ошибка в числе байт 1 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GenaSPB 11 8 февраля, 2020 Опубликовано 8 февраля, 2020 · Жалоба Моя возня в этой тебе вот тут Soft-NCO-DDS-на-микроконтроллере Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
domowoj 0 9 февраля, 2020 Опубликовано 9 февраля, 2020 · Жалоба В 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 А куда это вставить-то? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
muravei 3 9 февраля, 2020 Опубликовано 9 февраля, 2020 · Жалоба DDS на STM32F303 3 канала до1МГц https://radiokot.ru/forum/viewtopic.php?p=2497459#p2497459 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
uni 6 10 февраля, 2020 Опубликовано 10 февраля, 2020 (изменено) · Жалоба В оригинальной статье есть ссылка на архив. В архиве есть другой архив: Последняя версия ПО. В этом архиве есть папка Firmware, в которой находится Makefile. Эти опции являются ключами компоновщика, задающими адреса для секций таблиц с отсчётами формируемых сигналов. Ключи эти уже находятся в этом Makefile и вставлять их отдельно не надо. Нужно открыть файл в текстовом редакторе, поиском найти список этих ключей и заменить значения адресов указанным образом (начальные тройки поменять на единички). После этого нужно пересобрать проект, не забыв также заменить тип мк. Когда мы делаем такую замену, мы размещаем эти таблицы в конце памяти программ. Адреса для ATmega16 нам не подходят, т.к. они находятся выше 8К, доступных для ATmega8535. Если оставить цифры как есть и получить hex-файл, то мне трудно предсказать что будет, если попытаться этот файл прошить в мк, имеющий в 2 раза меньше флеш памяти. Удивительно ещё, что не было ошибки на каком-то из этапов. Изменено 10 февраля, 2020 пользователем uni Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
domowoj 0 10 февраля, 2020 Опубликовано 10 февраля, 2020 · Жалоба Спасибо , буду пробовать Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
uni 6 10 февраля, 2020 Опубликовано 10 февраля, 2020 (изменено) · Жалоба Я привык использовать самостоятельную сборку из консоли при помощи 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'а. Работает также. Изменено 10 февраля, 2020 пользователем uni Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
domowoj 0 10 февраля, 2020 Опубликовано 10 февраля, 2020 · Жалоба Спасибо uni, все работает! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться