Utilizzo modulo PWM per generare segnali analogici

  • marcoilgrande
  • Autore della discussione
  • Giovane Utente
  • Giovane Utente
Di più
6 Anni 4 Settimane fa - 6 Anni 4 Settimane fa #1 da marcoilgrande
ltlib uart e interrupt è stato creato da marcoilgrande
Ciao a tutti, riassillo di nuovo il forum... ho provato a riaddattare il codice pwm per far suonare un buzzer ma non suona come dovrebbe. Allego codice, ammetto di aver preso spunti su internet
Code:
#include <xc.h> //#include "PIC18F4550_config.h" #include "LTlib.h" #include "LTlib_delay.h" #include "LTlib_delay.c" #define XF 20000000 #define _XTAL_FREQ 20000000 #define TMR2PRESCALE 16 // TONES ========================================== #define c 261 #define d 293 #define e 329 #define f 349 #define g 392 #define a 440 #define b 493 #define C 523 #define D 587 #define E 659 #define F 698 #define G 784 // Define a special note, 'R', to represent a rest #define R 0 // ================================================== int tempo = 2000; int current_tone = 0; //current playing note int current_tone_duration = 0; //current note duration void SetupClock() { // OSCCONbits.IRCF = 0b110; //set internal oscillator to 4 Mhz // OSCCONbits.SCS = 0b00; //use oscillator defined by FOSC } void PWM1_Init(long desired_frequency) { // 1 - Definire e scrivere nel registro PR2 del pic, il periodo del PWM //2 - Definire il modulo CCPx come PWM //3 - Abilitare il timer TMR2 ed il suo prescaler opportunamente scelto in funzione del periodo //4 - Definire il duty cycle del segnale generato. // //Queste 4 operazioni possono essere scritte più o meno semplicemente in funzione del linguaggio usato. Ma anche se scritte in Assembler, non sono molto faticose. Io solitamente uso il "C" della CCS e basta una riga per operazione, grazie anche alle built in function del compilatore. //Come esempio ipotizziamo di usare CCP2 con uscita su RC1. //Dovremo stabilire per prima cosa il periodo del nostro segnale. //periodo PWM =[(PR2)+1]*4*Tosc*(TMR2 prescale value) //dove: - TMR2 prescale value è il valore di prescaler associato al Timer2 del 16f877 - PR2 è un registro (associato a Tmr2) da impostare con opportuno valore per ottenere il periodo voluto - Tosc è l’inverso della frequenza del quarzo esterno che fornisce il clock al PIC TMR2 prescale value può valere 1, 4, 16 e PR2 è un registro a 8 bit pertanto il valore deve essere compreso tra 0 e 255. Usando CCS come compilatore scriverei: // // setup timer_2(T2_DIV_BY_1,99,1); // setup CCP2( CCP_PWM); // setpwm2_duty (200);  PR2 = (XF / (desired_frequency * 4 * TMR2PRESCALE)) - 1; //(XF / (desired_frequency * 4 * TMR2PRESCALE)) - 1; current_tone = desired_frequency; } int PWM_Max_Duty() { return (XF / (current_tone * TMR2PRESCALE)); } void PWM1_Duty(unsigned int duty) { // CCPR1L = (unsigned char) (duty >> 2); // // if (duty & 0x0001) // CCP1CONbits.DC1B0 = 0x0001; // else // CCP1CONbits.DC1B0 = 0x0000; // // if (duty & 0x0002) // CCP1CONbits.DC1B1 = 0x0001; // else // CCP1CONbits.DC1B1 = 0x0000; if (duty < 1024) { duty = ((float) duty / 1023) * PWM_Max_Duty(); DC1B1 = duty & 2; //CCP1X = duty & 2; DC1B0 = duty & 1; // CCP1Y = duty & 1; CCPR1L = duty >> 2; } } void PWM1_Mode_On() { CCP1M3 = 1; CCP1M2 = 1; } void PWM1_Start() { PWM1_Mode_On(); #if TMR2PRESCALE == 1 T2CKPS0 = 0; T2CKPS1 = 0; #elif TMR2PRESCALE == 4 T2CKPS0 = 1; T2CKPS1 = 0; #elif TMR2PRESCALE == 16 T2CKPS0 = 1; T2CKPS1 = 1; #endif TMR2ON = 1; } void PWM1_Stop() { CCP1M3 = 0; CCP1M2 = 0; } void playTone() { //TODO: The Tone R is not implemented yet. if (current_tone > 0) { PWM1_Init(current_tone); PWM1_Duty(511);//511); delay_ms(current_tone_duration); PWM1_Duty(0); } } int main(int argc, char** argv) { short melody[] = {g, g, a, g, C, b, g, g, a, g, D, C, g, g, G, E, C, b, a, F, F, E, C, D, C}; char beats[] = {8, 8, 4, 4, 4, 2, 8, 8, 4, 4, 4, 2, 8, 8, 4, 4, 4, 4, 4, 8, 8, 4, 4, 4, 2}; // short melody[] = {E,F,G,G,E,F,G,G,E,F,G,E,F,G,G,E,F,G,G,G,F,F,E}; // char beats[] = {2,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4}; // char MELODY_LENGTH = sizeof (melody) / sizeof (melody[0]); SetupClock(); TRISCbits.TRISC2 = 0; //set Pin B3 as output PORTC = 0x00; PWM1_Init(500); //exact value doesn't matter at all, just not 0 PWM1_Duty(0); PWM1_Start(); while (1) { for (int i = 0; i < MELODY_LENGTH; i++) { current_tone = melody[i]; current_tone_duration = tempo / beats[i]; playTone(); delay_ms(tempo/200); } delay_ms(2000); } return 0; }


Grazie a tutti in anticipo! Purtroppo codici xc8 per buzzer pic18 non se ne vedono nemmeno in giro
Ultima Modifica 6 Anni 4 Settimane fa da marcoilgrande.

Si prega Accesso o Crea un account a partecipare alla conversazione.

  • Mauro Laurenti
  • Moderatore
  • Moderatore
Di più
6 Anni 3 Settimane fa #2 da Mauro Laurenti
Risposta da Mauro Laurenti al topic ltlib uart e interrupt
Salve Marco,

prima di entrare nei dettagli del software:
  • Qual'è lo schema elettrico che usi?
  • Quando dici che non suona come dovrebbe, che senti?

Con una singola nota funziona?

Saluti,

Mauro

Si prega Accesso o Crea un account a partecipare alla conversazione.

  • marcoilgrande
  • Autore della discussione
  • Giovane Utente
  • Giovane Utente
Di più
6 Anni 3 Settimane fa - 6 Anni 3 Settimane fa #3 da marcoilgrande
Risposta da marcoilgrande al topic ltlib uart e interrupt
suona ma il suono é parecchio acuto. Se invece configuro il pic con un oscillatore interno i toni hanno la tonalità giusta. Boh, nn ne capisco il perche.

Il circuito é uno di quelli preassemblati che vendono su ebay compatibili pic e arduino. Si vede un transistor in smd e una resistenza. Il tutto è su rc1 o rc2, nn ricordo, é luscita pic ccp1 del 18f4550
Ultima Modifica 6 Anni 3 Settimane fa da marcoilgrande.

Si prega Accesso o Crea un account a partecipare alla conversazione.

  • marcoilgrande
  • Autore della discussione
  • Giovane Utente
  • Giovane Utente
Di più
6 Anni 3 Settimane fa #4 da marcoilgrande
Risposta da marcoilgrande al topic ltlib uart e interrupt
Credo dipenda tutto dal timer.L'esempio è calibrato per 4 mhz. ho provato a portarlo a 20 ma non so bene dove operare. Presuno su PR2 ma non cambia nulla, forse bisogna toccare PWM_Max_Duty o forse su altro.

BOH

Si prega Accesso o Crea un account a partecipare alla conversazione.

  • marcoilgrande
  • Autore della discussione
  • Giovane Utente
  • Giovane Utente
Di più
5 Anni 10 Mesi fa #5 da marcoilgrande
Risposta da marcoilgrande al topic ltlib uart e interrupt
Nessuno mi sa aiutare?

Si prega Accesso o Crea un account a partecipare alla conversazione.

Moderatori: Mauro LaurentiPinnaStefAMatteo Garia

Registrati al sito

Accedi a tutte le risorse e articoli non visibili pubblicamente, puoi registrarti con pochi passi.

Registrati al sito LaurTec.

Forum - Ultimi messaggi