[an error occurred while processing this directive] [an error occurred while processing this directive]
Присоединяясь к сказанному...
(«Телесистемы»: Конференция «Микроконтроллеры и их применение»)
[an error occurred while processing this directive] [an error occurred while processing this directive] [an error occurred while processing this directive]

Отправлено CE 03 октября 2001 г. 22:16
В ответ на: Как заставить однокристалку говорить с помощю ШИМ? отправлено Volodya 02 октября 2001 г. 00:11

Хочу подкрепить примером. Не так давно делал говорящую штуковину и осталась отладочная программка. Работает. Наговаривается все на РС, потом режется на отдельные слова и пишется в ПЗУ (у меня 24С512 прим. 20 сек. речи). Для компиляции всех фраз в один массив делал отдельную прогу для РС. Она же формирует и "каталог" фраз в начале ПЗУ. Может разберетесь. ;-)

/*****************************************************************************
* Filename: Phrase.C *
******************************************************************************
* Выборка слова из ROM *
******************************************************************************
* External Clock Frequency: 8 MHz *
* Configuration Bit Settings *
* OSC: XT *
* WDT: Off *
* PWRTE: On *
* CP: Off *
*****************************************************************************/
#include "pic.h"
#include "i2c.h"
__CONFIG(FOSC0 | BODEN | UNPROTECT | CPD);

#define ROM 0xA0 /* I2C EEPROM */
#define MaxPhrase 32
unsigned int Address; // EPROM address
int WavLen;
unsigned int i;
struct SoundRec{
unsigned int SndOffs;
unsigned int SndSize;
}
union {
struct SoundRec SnDir;
char Bytes[4];
} DirEntry;

signed char predsample; // для ADPCMdecode
signed char index; // для ADPCMdecode

#include "adpcm_d.c" // decode routine

/***********************************************************************
* InitDev - This function initializes PORTs, and PWM *
***********************************************************************/
void InitDev(void)
{
INTCON=0;
ADCON1=OPTION=7;
TRISA=TRISB=TRISC=TRISD=TRISE=0;
PR2 = 63; // Set PWM for 32KHz period
T2CON = 0b00011000; //Postscale = 4
CCPR1L = 0x80;
/* initialize i2c */
SCL_DIR = I2Co;
SDA_DIR = I2Ci;
SDA = 1;
SCL = 1;
return;
}

/****************************************************************************
*
*****************************************************************************/
void PWMout(signed char sample){
while(!TMR2IF); // Wait for 8kHz to output
TMR2IF=0;
sample^=0x80;
CCPR1L = (sample>>2)&0x003f; // Write 6 bits
CCP1CON &= 0xcf; // to CCPR1L
if(sample&0x02) // Write 2 bits
CCP1X = 1; // to CCP1CON
if(sample&0x01) // to get 8-bit
CCP1Y = 1; // PWM

}
char PrepReadROM(unsigned int Address){ // Установка адреса 24512 для чтения
char i; // выход!=0 - норма
for(i=3;i;i--){
i2c_Stop();
i2c_Start();
if(i2c_SendByte(ROM+I2C_WRITE)) continue;
if(i2c_SendByte(*(((char*)&Address)+1))) continue; // HI byte
if(i2c_SendByte((char) (Address&0x00FF))) continue; // LO byte
i2c_Start();
if(i2c_SendByte(ROM+I2C_READ)) continue;
break;
}
return(i);
}
/***************************/
char SayPhrase(char PhrNo){
char *c=&(DirEntry.Bytes);
unsigned char code; // EPROM byte
signed char sample; // decoded sample
unsigned char Pack;
char i;
PhrNo&=MaxPhrase-1;
if(!PrepReadROM(PhrNo<<2)) return(1);
for(i=4;i;i--) *c++=i2c_ReadByte(I2C_ACK);
i2c_ReadByte(I2C_NACK);
if((WavLen=DirEntry.SnDir.SndSize)==0) return(2);
if(!PrepReadROM(DirEntry.SnDir.SndOffs)) return(1);
predsample = 0; // Clear ADPCM structure
index = 0;
do{
code=i2c_ReadByte(I2C_ACK);
PWMout(ADPCMDecoder(code));
code>>=3;
PWMout(ADPCMDecoder(code));
Pack=(code>>3) & 0x3;
if(!--WavLen) break;
code=i2c_ReadByte(I2C_ACK);
PWMout(ADPCMDecoder(Pack|((code&1)<<2)));
code>>=1;
PWMout(ADPCMDecoder(code));
code>>=3;
PWMout(ADPCMDecoder(code));
Pack=code&8 ? 1:0;
if(!--WavLen) break;
code=i2c_ReadByte(I2C_ACK);
PWMout(ADPCMDecoder(Pack|((code&3)<<1)));
code>>=2;
PWMout(ADPCMDecoder(code));
code>>=3;
PWMout(ADPCMDecoder(code));
} while(--WavLen); // Has Address overflowed?
i2c_ReadByte(I2C_NACK);
i2c_Stop();
return(0);
}
/*****************************************************************************
* main - This function controls everything, kinda like a god. *
*****************************************************************************/
void main(void)
{
unsigned int i;

InitDev(); // Initialize the PIC
TMR2IF = 0; // Enable Timer2 Interrupts
// TMR2IE = 1;
// PEIE = 1; // Enable PEIE and GIE
// GIE = 1;
TRISC2 = 0; // Make PWM an output
TMR2ON = 1; // Enable Timer2
CCP1CON = 0x0f; // Enable PWM
while(1){
for(i=0;i<65535;i++);
for(i=0;i<65535;i++);
for(i=0;i<65535;i++);
PORTD=8;
SayPhrase(0);
PORTD=9;
SayPhrase(1);
PORTD=10;
SayPhrase(2);
PORTD=11;
SayPhrase(3);
PORTD=12;
SayPhrase(4);
PORTD=13;
SayPhrase(5);
PORTD=5;
SayPhrase(3);
SayPhrase(31);
PORTD=7;
SayPhrase(30);
SayPhrase(8);
for(i=0;i<40000;i++);
} TMR2ON = 0; // Disable Timer2
CCP1CON = 0; // Disable PWM
TRISC2 = 1; // Make PWM input
}

/*****************************************************************************
* __INT - This is the interrupt service routine. Only Timer 2 overflow *
* is implemented. *
*****************************************************************************/
static void interrupt _INT(void){
if(TMR2IF) // Timer2 overflow interrupt
{
TMR2IF = 0; // Clear flag
PORTD^=8;
}
return;
}

P.S. В Инете я не часто, поэтому на вопросы ответить быстро не обещаю.

Составить ответ  |||  Конференция  |||  Архив

Ответы



Перейти к списку ответов  |||  Конференция  |||  Архив  |||  Главная страница  |||  Содержание  |||  Без кадра

E-mail: info@telesys.ru