- Messaggi: 22
- Ringraziamenti ricevuti 0
Utilizzo modulo PWM per generare segnali analogici
- marcoilgrande
- Autore della discussione
- Giovane Utente
-
Less
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
Grazie a tutti in anticipo! Purtroppo codici xc8 per buzzer pic18 non se ne vedono nemmeno in giro
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.
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:
Con una singola nota funziona?
Saluti,
Mauro
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
-
Less
Di più
- Messaggi: 22
- Ringraziamenti ricevuti 0
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
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
-
Less
Di più
- Messaggi: 22
- Ringraziamenti ricevuti 0
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
BOH
Si prega Accesso o Crea un account a partecipare alla conversazione.
- marcoilgrande
- Autore della discussione
- Giovane Utente
-
Less
Di più
- Messaggi: 22
- Ringraziamenti ricevuti 0
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 Laurenti, Pinna, StefA, Matteo Garia
Registrati al sito
Accedi a tutte le risorse e articoli non visibili pubblicamente, puoi registrarti con pochi passi.
Forum - Ultimi messaggi
-
- progetto can
- da marcelloraja
-
- MODULO GSM SIM900A
- da Mauro Laurenti
-
- Freedom III e compilazioni fallite
- da Mauro Laurenti
-
- Gestione degli errori su comunicazione seriale
- da Mauro Laurenti
-
- Timer0 e interrupt
- da Mauro Laurenti