Entrar    Registrar

Usando w25q32 com 18Fxx

Software e Hardware para uC PIC

Moderadores: aluis-rcastro, guest2003, 51, Renie

  • Autor
    Mensagem

Usando w25q32 com 18Fxx

Mensagempor vtrx » 27 Mai 2020 17:54

Alguém tem algum exemplo de como ler/escrever nesta memória para substituir as do tipo 24cxx?
Avatar do usuário
vtrx
Dword
 
Mensagens: 1965
Registrado em: 20 Abr 2008 21:01

Re: Usando w25q32 com 18Fxx

Mensagempor tcpipchip » 28 Mai 2020 08:49

tens que estudar interface SPI primeiro!

E veja, ela é uma FLASH e nao EEPROM

Se nao me engano o esp utiliza ela e ai podes estudar a lib FS
------------------------------------------
http://www.youtube.com/tcpipchip
Avatar do usuário
tcpipchip
Dword
 
Mensagens: 6134
Registrado em: 11 Out 2006 22:32
Localização: TCPIPCHIPizinho!

Re: Usando w25q32 com 18Fxx

Mensagempor Rodrigo_P_A » 28 Mai 2020 11:15

Essas memórias são baratas mas veja o principal: você não consegue escrever somente um byte nela, só consegue escrever em blocos, então se vc quer escrever byte a byte, você tem que criar algum algorítimo e vai usar RAM pra isso, pelo menos a quantidade do SETOR, cada setor tem 4KB , e pelo que eu lembro esses PICs tem pouca RAM, ou seja, vocẽ num vai conseguir alterar só um byte, pois para isso você teria que ler um setor interno para a RAM, modificar, apagar o setor, e regravar. basicamente é isso. Pense bem
---
Avatar do usuário
Rodrigo_P_A
Dword
 
Mensagens: 2097
Registrado em: 12 Out 2006 18:27
Localização: Osasco - S.P - Brasil

Re: Usando w25q32 com 18Fxx

Mensagempor vtrx » 28 Mai 2020 17:19

Eu peguei um exemplo na net,para tocar wav,e ele le byte a byte sequencialmente.
Peguei um outro esboço e ele le e grava um byte.
Voces que tem paciência poderiam me ajudar,se eu usar uma dessas vou economizar muito espaço e pinos num projeto meu.
Montei um esboço aqui,bem mal feito,e não consegui fazer funcionar,isso baseado no projeto Canario eletronico.
segue um e o outro que não testei.
Toca wav 25Q64:
Código: Selecionar todos
/*******************************************************************************



    CANÁRIO ELETRÔNICO

    Modo PWM - utiliza o PWM interno do pic a 19,53 khz.

    Autor: Claudio Lários

    Data: 02/11/2017

    Microcontrolador: PIC 16f628A
    FLASH: 25Q64 (usada como 'BIOS' de alguns notebook, pc, roteadores, etc)

    Objetivo: Ao ligar a alimentação deverá reproduzir continuamanete o canto
    de um canário belga.

    Parte integrante do blog PICSOURCE (LARIOS.TECNOLOGIA.WS)
    Proposta didática apenas, sendo testada somente em placa de protoboard.

******************************************************************************/


#include <16F628A.h>
#use delay(clock=20000000)//USE XTAL DE 20MHZ
#fuses NOWDT,HS, NOPUT, NOPROTECT, NOBROWNOUT, NOMCLR, NOLVP, NOCPD
#use fast_io(a)
#use fast_io(b)
#ZERO_RAM



#byte trisa= 0x85
#byte trisb= 0x86
#byte porta= 0x05
#byte portb= 0x06
#byte pr2=   0x92
#byte ccp1l= 0x15


#bit    flagt2       = 0x0C.1  //flag do timer 2
#bit    som          = 0x06.3  //pino 9 saida de som
#bit    tris_som     = 0x86.3  //sentido
#bit    mosi         = 0x05.1  //pino 18
#bit    miso         = 0x05.4  //pino 3
#bit    cs           = 0x05.3  //pino 2
#bit    slk          = 0x05.0  //pino 17




//variáveis globais
unsigned int16 b;//auxiliar


/*==============================================================================

                      ROTINAS DE COMUNICAÇÃO SPI

==============================================================================*/


/*==============================================================================
     GERA SINAL DE CLOCK PARA A FLASH
==============================================================================*/

void clock(void){ slk=1; delay_us(1);slk=0; delay_us(1);}

/*==============================================================================
    ENVIA 8 BITS PARA A FLASH
==============================================================================*/
void env8(int8 zbuf1){
  int8 a3;
  for(a3=0;a3<8;a3++){
  if(bit_test(zbuf1,7)) mosi=1; else mosi=0;
   clock();
   zbuf1<<=1;
  }
}
/*==============================================================================
     RECEBE 8 BITS DA FLASH
==============================================================================*/

int8 recebe_flash_8bits(void){
 int8 a5,b;
 b=0;
 for (a5=0;a5<8;a5++){
  shift_left(&b,1,miso); //original
  clock();
 }
   return (b);
}


/*==============================================================================
     ROTINA DE REPRODUÇÃO DE SOM GRAVADO NA MEMÓRIA FLASH EXTERNA
==============================================================================*/

void reproduzir(int32 address){
 int8 buf;
 
 
  cs=0;
  env8(0x03);//comando de reproduzir em modo contínuo
  env8(make8(address,2));//pega endereço inicial
  env8(make8(address,1));
  env8(make8(address,0));
  tris_som=0;//port de som como saída
  for(;;){// reproduz até encontrar 0x22 no código
      buf=recebe_flash_8bits(); //recebe byte
      if(buf==0x22) {/*tris_som=1; */cs=1;break;} //para no fim do arquivo
      while(!flagt2) ;//aguarda 'pwm' finalizar processo
      ccp1l=buf;//carga do valor do pwm
      flagt2=0;//zera flag tmr2
     
  }

  cs=1;
}

/*==============================================================================
         ROTINAS DE ENDEREÇAMENTO DA FLASH 25q64
==============================================================================*/


void canario(){
 reproduzir(0x16c0);//
}



/*==============================================================================
                      ROTINA MAIN
==============================================================================*/

void main() {

   setup_counters(RTCC_INTERNAL,RTCC_DIV_1);
   setup_timer_1( T1_INTERNAL|T1_DIV_BY_1);//  prescaller =1/2/4/8
   setup_timer_2 ( T2_DIV_BY_1, 0, 1);
   setup_comparator(NC_NC_NC_NC);
   setup_ccp1(CCP_PWM);
   setup_vref(FALSE);
   pr2=0xff;//periodo max
   cs=1;
   trisa=0b11110000;
   trisb=0;
   porta=0; //desliga saídas

/*
   fala_nome_montagem();//nome do aparelho
   delay_ms(100);
   fala_blog();//blog
 */ 
   delay_ms(500);

/*==============================================================================
                    LOOP PRINCIPAL DE REPETIÇÃO
==============================================================================*/
 for(;;){
     
     canario();
   }//for(;;)
}//main


Tentei converter para um mdo que entendo e usando um 18F2250:
Código: Selecionar todos
#include <18F2550.h>
#fuses XTPLL,NOWDT,PROTECT,NOLVP,NODEBUG,USBDIV,PLL1,CPUDIV1,VREGEN,MCLR,CPB,CPD  //4MHZ,USB-48MHZ,CPU-48MHZ
//#fuses XTPLL,NOWDT,NOLVP,NODEBUG,USBDIV,PLL1,CPUDIV1,VREGEN,MCLR,CPB,BROWNOUT,BORV20 //SEM PROTEÇÃO
//#fuses XTPLL,NOWDT,PROTECT,NOLVP,NODEBUG,USBDIV,PLL1,CPUDIV1,VREGEN,NOMCLR,CPB,CPD  //4MHZ,USB-48MHZ,CPU-48MHZ (NOMCLR=RE3 como entrada)

#use delay(clock=48000000)


#use fast_io(c)
#use fast_io(b)

//#bit    flagt2       = 0x0C.1  //flag do timer 2
//#bit    som          = 0x06.3  //pino 9 saida de som
//#bit    tris_som     = 0x86.3  //sentido
//#bit    mosi         = 0x05.1  //pino 18
//#bit    miso         = 0x05.4  //pino 3
//#bit    cs           = 0x05.3  //pino 2
//#bit    slk          = 0x05.0  //pino 17
#define mosi PIN_B0
#define miso PIN_B1
#define cs   PIN_B2
#define slk  PIN_B3

// Define taxa de amostragem
#define FOSC      48000000   
#define T2_FREQ   8000        //22050       // 22 KHz
#define Tam_wav   65535
#define PR2    FOSC/4/T2_FREQ
#define wav11025  4
#define wav22050  2

//variáveis globais
unsigned int16 b;//auxiliar
int      wait;

/*==============================================================================

                      ROTINAS DE COMUNICAÇÃO SPI

==============================================================================*/


/*==============================================================================
     GERA SINAL DE CLOCK PARA A FLASH
==============================================================================*/

void clock(void){ output_high(slk); delay_us(1);output_low(slk); delay_us(1);}

/*==============================================================================
    ENVIA 8 BITS PARA A FLASH
==============================================================================*/
void env8(int8 zbuf1)
{
  int8 a3;
  for(a3=0;a3<8;a3++)
  {
  if(bit_test(zbuf1,7)) output_high(mosi); else output_low(mosi);
   clock();
   zbuf1<<=1;
  }
}
/*==============================================================================
     RECEBE 8 BITS DA FLASH
==============================================================================*/

int8 recebe_flash_8bits(void)
{
 int8 a5,b;
 b=0;
 for (a5=0;a5<8;a5++)
 {
  shift_left(&b,1,miso); //original
  clock();
 }
   return (b);
}


/*==============================================================================
     ROTINA DE REPRODUÇÃO DE SOM GRAVADO NA MEMÓRIA FLASH EXTERNA
==============================================================================*/

void reproduzir(int32 address)
{
 int8 buf;
 int16 i;
 
  output_low(cs);                    //inicia instrução de leitura
  env8(0x03);//comando de reproduzir em modo contínuo
  env8(make8(address,2));//pega endereço inicial
  env8(make8(address,1));
  env8(make8(address,0));
  //tris_som=0;//port de som como saída
  for(i=0; i < 65535; i++)
  {// reproduz até encontrar 0x22 no código
      buf = recebe_flash_8bits(); //recebe byte
      //if(buf==0x22) {/*tris_som=1; */output_high(cs);break;} //para no fim do arquivo
      wait=wav11025;
      while(wait);   
      set_pwm1_duty(buf);   
  }
  output_high(cs);                 //finaliza a leitura
}

/*==============================================================================
         ROTINAS DE ENDEREÇAMENTO DA FLASH 25q64
==============================================================================*/
void canario()
{
 reproduzir(0x16c0);//
}

// --------------------------------------------------------------------------
#INT_TIMER2
void int_tmr2()
{
   if(wait) wait--;
}
//...........................................................................
/*==============================================================================
                      ROTINA MAIN
==============================================================================*/
void main()
{
//   set_tris_a(0b11111111);
   set_tris_b(0b11110000);
   set_tris_c(0b11110001);
  // output_b ( 0x00 );
   
   
   setup_timer_2(T2_DIV_BY_1, PR2, 1);
   setup_ccp1(CCP_PWM);
   
   enable_interrupts(GLOBAL);
   enable_interrupts(INT_TIMER2);
   
   output_high(cs);
   output_low(mosi);
   output_low(slk);

/*
   fala_nome_montagem();//nome do aparelho
   delay_ms(100);
   fala_blog();//blog
 */ 

/*==============================================================================
                    LOOP PRINCIPAL DE REPETIÇÃO
==============================================================================*/
 for(;;)
 {
  reproduzir(0x0000);
  delay_ms(1000);
 }//for(;;)
}//main


A parte do PWM,neste ultimo código,é funcional,mas usando uma 24C512.

Por ultimo,código para gravar um byte ou ler um byte,não testado ainda.
Código: Selecionar todos
#include <16F628A.h>

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES HS                       //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES PUT                      //Power Up Timer
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NOBROWNOUT               //No brownout reset
#FUSES MCLR                     //Master Clear pin enabled
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD                    //No EE protection

#define EEPROM_SELECT PIN_B0
#define EEPROM_CLK    PIN_B1
#define EEPROM_DI     PIN_B2
#define EEPROM_DO     PIN_B3

#use delay(clock=20000000)
#use rs232(baud=115200,parity=N,xmit=PIN_B2,rcv=PIN_B1,bits=8)

#include "W25Xxx.C"
#include <stdio.h>


BYTE cmd[5], co = 0, data = 'X';
int32 address;

#int_TBE                         //serial empty buffer
void  TBE_isr(void)
{
   disable_interrupts(INT_TBE);
   
   switch(cmd[0])
   {
      case 'E':
         putc('S');
      break;   
      case 'W':
         putc('S');
      break;     
      case 'R':
         putc(data);
      break;
   }
   
   enable_interrupts(INT_RDA);
}

#int_RDA                      //INTERRUPÇÃO DA SERIAL (serial receive buffer)
void  RDA_isr(void)
{
   cmd[co ++] = getc();
   
   if(co == 5)
   {
      disable_interrupts(INT_RDA);     
      co = 0;     
      address = ((int32) cmd[1]) << 16;
      address |= ((int32) cmd[2]) << 8;
      address |= (int32) cmd[3];   
      switch(cmd[0])
      {
         case 'E':
            erase_ext_eeprom();
         break;
         
         case 'W':
            write_ext_eeprom(address, cmd[4]);
         break;
         
         case 'R':
            data = read_ext_eeprom(address);
         break;
      }   
      enable_interrupts(INT_TBE);
   }
}

void main()
{
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_ccp1(CCP_OFF);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   
   init_ext_eeprom();
   
   disable_interrupts(INT_TBE);
   enable_interrupts(INT_RDA);
   enable_interrupts(GLOBAL);

   //TODO: User Code
   
   while(TRUE);
}


Código: Selecionar todos
///////////////////////////////////////////////////////////////////////////
////   Library for a Winbond W25Xxx (128 KB --> 16 MB)                 ////
////                                                                   ////
////   init_ext_eeprom();    Call before the other functions are used  ////
////                                                                   ////
////   write_ext_eeprom(a, d);  Write the byte d to the address a      ////
////                                                                   ////
////   d = read_ext_eeprom(a);   Read the byte d from the address a    ////
////                                                                   ////
////   b = ext_eeprom_ready();  Returns TRUE if the eeprom is ready    ////
////                            to receive opcodes                     ////
////                                                                   ////
////   The main program may define EEPROM_SELECT, EEPROM_DI, EEPROM_DO ////
////   and EEPROM_CLK to override the defaults below.                  ////
////                                                                   ////
////                                                                   ////
////                      Pin Layout                                   ////
////   -----------------------------------------------                 ////
////   |    __                                       |                 ////
////   | 1: CS   EEPROM_SELECT | 8: VCC   +5V        |                 ////
////   |                       |    ____             |                 ////
////   | 2: DO   EEPROM_DO     | 7: HOLD  +5V        |                 ////
////   |    __                 |                     |                 ////
////   | 3: WP   +5V           | 6: CLK   EEPROM_CLK |                 ////
////   |                       |                     |                 ////
////   | 4: GND  Ground        | 5: DIO   EEPROM_DI  |                 ////
////   -----------------------------------------------                 ////
////                                                                   ////
///////////////////////////////////////////////////////////////////////////
////        (C) Copyright 1996, 2003 Custom Computer Services          ////
//// This source code may only be used by licensed users of the CCS C  ////
//// compiler.  This source code may only be distributed to other      ////
//// licensed users of the CCS C compiler.  No other use, reproduction ////
//// or distribution is permitted without written permission.          ////
//// Derivative programs created using this software in object code    ////
//// form are not restricted in any way.                               ////
///////////////////////////////////////////////////////////////////////////


#ifndef EEPROM_SELECT
 #define EEPROM_SELECT PIN_A0
#endif
#ifndef EEPROM_CLK
 #define EEPROM_CLK    PIN_A1
#endif
#ifndef EEPROM_DI
 #define EEPROM_DI     PIN_A2
#endif
#ifndef EEPROM_DO
 #define EEPROM_DO     PIN_A3
#endif

#define EEPROM_ADDRESS  int32

void init_ext_eeprom()
{
   output_high(EEPROM_SELECT);
   output_low(EEPROM_DI);
   output_low(EEPROM_CLK);
}

BOOLEAN ext_eeprom_ready()
{
   BYTE rdsr, i, data;   
   rdsr = 0x05;                  // rdsr opcode  (Read Status Register 1)
   output_low(EEPROM_SELECT);   
   for(i=0; i<8; ++i)
   {
      output_bit(EEPROM_DI, shift_left(&rdsr, 1, 0));
      output_high(EEPROM_CLK);   // data latches
      output_low(EEPROM_CLK);    // back to idle
   } 
   for(i=0; i<8; ++i)
   {
      output_high(EEPROM_CLK);
      shift_left(&data, 1, input(EEPROM_DO));
      output_low(EEPROM_CLK);    // data latches & back to idle
   }   
   output_high(EEPROM_SELECT);   
   return !bit_test(data, 0);
}

void erase_ext_eeprom()
{
   BYTE i, wren, erase;
   
   wren  = 0x06;                  // wren opcode (Write Enable 06H)
   erase = 0xc7;                 // chip erase
   
   // Wait until the eeprom is done with a previous write
   while(!ext_eeprom_ready());
   
   output_low(EEPROM_SELECT);   
   for(i=0; i<8; ++i)
   {
      output_bit(EEPROM_DI, shift_left(&wren, 1, 0));
      output_high(EEPROM_CLK);   // data latches
      output_low(EEPROM_CLK);    // back to idle
   } 
   output_high(EEPROM_SELECT); 
   output_low(EEPROM_SELECT); 
   for(i=0; i<8; ++i)
   {
      output_bit(EEPROM_DI, shift_left(&erase, 1, 0));
      output_high(EEPROM_CLK);   // data latches
      output_low(EEPROM_CLK);    // back to idle
   } 
   output_high(EEPROM_SELECT); 
   delay_ms(40000);              // tCE
}

void write_ext_eeprom(EEPROM_ADDRESS address, BYTE data)
{
   BYTE cmd[5], i, wren;
   
   wren   = 0x06;                  // wren opcode (Write Enable 06H)
   cmd[0] = data;
   cmd[1] = (BYTE) address;
   cmd[2] = (BYTE) (address >> 8);
   cmd[3] = (BYTE) (address >> 16);
   cmd[4] = 0x02;
   
   // Wait until the eeprom is done with a previous write
   while(!ext_eeprom_ready());
   
   output_low(EEPROM_SELECT); 
   for(i=0; i<8; ++i)
   {
      output_bit(EEPROM_DI, shift_left(&wren, 1, 0));
      output_high(EEPROM_CLK);   // data latches
      output_low(EEPROM_CLK);    // back to idle
   }   
   output_high(EEPROM_SELECT);   
   output_low(EEPROM_SELECT);   
   for(i=0; i<40; ++i)
   {
      output_bit(EEPROM_DI, shift_left(cmd, 5, 0));
      output_high(EEPROM_CLK);   // data latches
      output_low(EEPROM_CLK);    // back to idle
   }   
   output_high(EEPROM_SELECT);   
   delay_ms(3);                  // tPP
}

BYTE read_ext_eeprom(EEPROM_ADDRESS address)
{
   BYTE cmd[4], i, data;
   
   cmd[0] = (BYTE) address;
   cmd[1] = (BYTE) (address >> 8);
   cmd[2] = (BYTE) (address >> 16);
   cmd[3] = 0x03;                   //(Read Data 03H)
   
   // Wait until the eeprom is done with a previous write
   while(!ext_eeprom_ready());
   
   output_low(EEPROM_SELECT);   
   for(i=0; i<32; ++i)
   {
      output_bit(EEPROM_DI, shift_left(cmd, 4, 0));
      output_high(EEPROM_CLK);   // data latches
      output_low(EEPROM_CLK);    // back to idle
   }
   
   for(i=0; i<8; ++i)
   {
      output_high(EEPROM_CLK);
      shift_left(&data, 1, input(EEPROM_DO));
      output_low(EEPROM_CLK);    // data latches & back to idle
   }   
   output_high(EEPROM_SELECT);   
   return(data);
}


Não testei e não tenho o esquema do hardware.
#include "W25Xxx.C":
Avatar do usuário
vtrx
Dword
 
Mensagens: 1965
Registrado em: 20 Abr 2008 21:01

Re: Usando w25q32 com 18Fxx

Mensagempor Rodrigo_P_A » 28 Mai 2020 17:24

Sinto muito, eu num tenho como ajudar com o código.
---
Avatar do usuário
Rodrigo_P_A
Dword
 
Mensagens: 2097
Registrado em: 12 Out 2006 18:27
Localização: Osasco - S.P - Brasil

Re: Usando w25q32 com 18Fxx

Mensagempor vtrx » 28 Mai 2020 21:06

Consegui.
O problema agora é achar o melhor método (simples) de fazer a interface entre o PIC 5v como a Flash 3.3.
O 'circuito teste' esta variando o som com muito ruído se colocar a mão nos fios,e o volume é extremamente baixo se tentar escutar direto da saída PWM do PIC,tive que usar uma caixinha amplificada.
Acho que é por causa da flash ser de 3.3v e o PIC 5v.
No circuito comum com Eeprom e PIC 5 5V o audio sai perfeito e com bom volume,ja neste experimento com a 25Q32 o áudio contem muito ruído de fundo.
Amanhã vou tentar descobrir o porque destes problemas.
Se alguém quiser experimentar,o código usa o 18F2550 com cristal de 4MHZ e PWM CCP1(RC2),som wav teste gravado a 8 bits mono 11000 KHZ.

...

Depois de resolver estes problemas que apareceram,vou testar o código que grava dados.
Editado pela última vez por vtrx em 29 Mai 2020 12:29, em um total de 1 vez.
Avatar do usuário
vtrx
Dword
 
Mensagens: 1965
Registrado em: 20 Abr 2008 21:01

Re: Usando w25q32 com 18Fxx

Mensagempor ze » 29 Mai 2020 11:18

Minha contribuição é te dizer que este mc possui interface spi no hw o que te economiza recurso de sw e claro, maior eficiência. Algo como vc coloca o byte no buffer, liga um bit e espera o flag. Confirme no seu d.s.
https://www.microchip.com/wwwproducts/en/en010280
vtrx escreveu:O problema agora é achar o melhor método (simples) de fazer a interface entre o PIC 5v como a Flash 3.3.

Quanto a isso é bem simples. De 5 pra 3 bastam resistores divisores de tensão minimamente calculados. De 3 pra 5 talvez nem precise pois o mc pode entender 3 como nível alto e operar a contento. Teste
Avatar do usuário
ze
Dword
 
Mensagens: 1642
Registrado em: 05 Jun 2007 14:32

Re: Usando w25q32 com 18Fxx

Mensagempor vtrx » 29 Mai 2020 12:34

Podem esquecer o código que postei ontem,tem algo incomum nele.
O que funciona é este debaixo,inclusive não apresenta ruidos no audio.
Na verdade o que eu queria era não precisar de usar SDcard no projeto e aproveitar os PIC que tenho.

Código: Selecionar todos
/*******************************************************************************
Play wav 25QxxFV

******************************************************************************/
#include <18F2550.h>
#fuses XTPLL,NOWDT,PROTECT,NOLVP,NODEBUG,USBDIV,PLL1,CPUDIV1,VREGEN,MCLR,CPB,CPD  //4MHZ,USB-48MHZ,CPU-48MHZ
//#fuses XTPLL,NOWDT,NOLVP,NODEBUG,USBDIV,PLL1,CPUDIV1,VREGEN,MCLR,CPB,BROWNOUT,BORV20 //SEM PROTEÇÃO
//#fuses XTPLL,NOWDT,PROTECT,NOLVP,NODEBUG,USBDIV,PLL1,CPUDIV1,VREGEN,NOMCLR,CPB,CPD  //4MHZ,USB-48MHZ,CPU-48MHZ (NOMCLR=RE3 como entrada)

#use delay(clock=48000000)

#define EEPROM_SELECT PIN_B2
#define EEPROM_CLK    PIN_B3
#define EEPROM_DI     PIN_B0
#define EEPROM_DO     PIN_B1

#include <W25Xxx.c>

#use fast_io(c)
#use fast_io(b)
 

// Define taxa de amostragem(algoritimo não exato)
#define Tam_wav   908881        //Tamanho do bytes de áudio
#define PR2       1500
#define wav11025  4
#define wav22050  2

int            wait;
//-------------------------------------------------------------------------
void Play_wav(int32 address)
{
   BYTE cmd[4], i, data;
   int32 Loop;
   
   cmd[0] = (BYTE) address;
   cmd[1] = (BYTE) (address >> 8);
   cmd[2] = (BYTE) (address >> 16);
   cmd[3] = 0x03;                   //(Read Data 03H)
   
   // Wait until the eeprom is done with a previous write
   while(!ext_eeprom_ready());
   output_low(EEPROM_SELECT);
//....................................................   
   for(i=0; i<32; ++i)
   {
      output_bit(EEPROM_DI, shift_left(cmd, 4, 0));
      output_high(EEPROM_CLK);   // data latches
      output_low(EEPROM_CLK);    // back to idle
   }
for(Loop=0; Loop < Tam_wav; Loop++)             
  { 
   for(i=0; i<8; ++i)
   {
      output_high(EEPROM_CLK);
      shift_left(&data, 1, input(EEPROM_DO));
      output_low(EEPROM_CLK);    // data latches & back to idle
   }
       wait=wav11025;
       while(wait);   
      set_pwm1_duty(data);         //saida analogica RC2   
  }   
 
   output_high(EEPROM_SELECT);   
}
//============================================================================
#INT_TIMER2
void int_tmr2()
{
   if(wait) wait--;
}
//============================================================================
void main()
{
//   set_tris_a(0b11111111);
   set_tris_b(0b11110000);
   set_tris_c(0b11110001);
  // output_b ( 0x00 );
   
   setup_timer_2(T2_DIV_BY_1, PR2, 1);
   setup_ccp1(CCP_PWM);
   setup_vref(FALSE);
   
   enable_interrupts(GLOBAL);
   enable_interrupts(INT_TIMER2);
   
   init_ext_eeprom();
   
 while(1)
 {
  Play_wav(0x0000);
  delay_ms(1000);
 }
 
}
//....


W25Xxx.c:

Código: Selecionar todos
///////////////////////////////////////////////////////////////////////////
////   Library for a Winbond W25Xxx (128 KB --> 16 MB)                 ////
////                                                                   ////
////   init_ext_eeprom();    Call before the other functions are used  ////
////                                                                   ////
////   write_ext_eeprom(a, d);  Write the byte d to the address a      ////
////                                                                   ////
////   d = read_ext_eeprom(a);   Read the byte d from the address a    ////
////                                                                   ////
////   b = ext_eeprom_ready();  Returns TRUE if the eeprom is ready    ////
////                            to receive opcodes                     ////
////                                                                   ////
////   The main program may define EEPROM_SELECT, EEPROM_DI, EEPROM_DO ////
////   and EEPROM_CLK to override the defaults below.                  ////
////                                                                   ////
////                                                                   ////
////                      Pin Layout                                   ////
////   -----------------------------------------------                 ////
////   |    __                                       |                 ////
////   | 1: CS   EEPROM_SELECT | 8: VCC   +5V        |                 ////
////   |                       |    ____             |                 ////
////   | 2: DO   EEPROM_DO     | 7: HOLD  +5V        |                 ////
////   |    __                 |                     |                 ////
////   | 3: WP   +5V           | 6: CLK   EEPROM_CLK |                 ////
////   |                       |                     |                 ////
////   | 4: GND  Ground        | 5: DIO   EEPROM_DI  |                 ////
////   -----------------------------------------------                 ////
////                                                                   ////
///////////////////////////////////////////////////////////////////////////
////        (C) Copyright 1996, 2003 Custom Computer Services          ////
//// This source code may only be used by licensed users of the CCS C  ////
//// compiler.  This source code may only be distributed to other      ////
//// licensed users of the CCS C compiler.  No other use, reproduction ////
//// or distribution is permitted without written permission.          ////
//// Derivative programs created using this software in object code    ////
//// form are not restricted in any way.                               ////
///////////////////////////////////////////////////////////////////////////


#ifndef EEPROM_SELECT
 #define EEPROM_SELECT PIN_A0
#endif
#ifndef EEPROM_CLK
 #define EEPROM_CLK    PIN_A1
#endif
#ifndef EEPROM_DI
 #define EEPROM_DI     PIN_A2
#endif
#ifndef EEPROM_DO
 #define EEPROM_DO     PIN_A3
#endif

#define EEPROM_ADDRESS  int32

void init_ext_eeprom()
{
   output_high(EEPROM_SELECT);
   output_low(EEPROM_DI);
   output_low(EEPROM_CLK);
}

BOOLEAN ext_eeprom_ready()
{
   BYTE rdsr, i, data;   
   rdsr = 0x05;                  // rdsr opcode  (Read Status Register 1)
   output_low(EEPROM_SELECT);   
   for(i=0; i<8; ++i)
   {
      output_bit(EEPROM_DI, shift_left(&rdsr, 1, 0));
      output_high(EEPROM_CLK);   // data latches
      output_low(EEPROM_CLK);    // back to idle
   } 
   for(i=0; i<8; ++i)
   {
      output_high(EEPROM_CLK);
      shift_left(&data, 1, input(EEPROM_DO));
      output_low(EEPROM_CLK);    // data latches & back to idle
   }   
   output_high(EEPROM_SELECT);   
   return !bit_test(data, 0);
}

void erase_ext_eeprom()
{
   BYTE i, wren, erase;
   
   wren  = 0x06;                  // wren opcode (Write Enable 06H)
   erase = 0xc7;                 // chip erase
   
   // Wait until the eeprom is done with a previous write
   while(!ext_eeprom_ready());
   
   output_low(EEPROM_SELECT);   
   for(i=0; i<8; ++i)
   {
      output_bit(EEPROM_DI, shift_left(&wren, 1, 0));
      output_high(EEPROM_CLK);   // data latches
      output_low(EEPROM_CLK);    // back to idle
   } 
   output_high(EEPROM_SELECT); 
   output_low(EEPROM_SELECT); 
   for(i=0; i<8; ++i)
   {
      output_bit(EEPROM_DI, shift_left(&erase, 1, 0));
      output_high(EEPROM_CLK);   // data latches
      output_low(EEPROM_CLK);    // back to idle
   } 
   output_high(EEPROM_SELECT); 
   delay_ms(40000);              // tCE
}

void write_ext_eeprom(EEPROM_ADDRESS address, BYTE data)
{
   BYTE cmd[5], i, wren;
   
   wren   = 0x06;                  // wren opcode (Write Enable 06H)
   cmd[0] = data;
   cmd[1] = (BYTE) address;
   cmd[2] = (BYTE) (address >> 8);
   cmd[3] = (BYTE) (address >> 16);
   cmd[4] = 0x02;
   
   // Wait until the eeprom is done with a previous write
   while(!ext_eeprom_ready());
   
   output_low(EEPROM_SELECT); 
   for(i=0; i<8; ++i)
   {
      output_bit(EEPROM_DI, shift_left(&wren, 1, 0));
      output_high(EEPROM_CLK);   // data latches
      output_low(EEPROM_CLK);    // back to idle
   }   
   output_high(EEPROM_SELECT);   
   output_low(EEPROM_SELECT);   
   for(i=0; i<40; ++i)
   {
      output_bit(EEPROM_DI, shift_left(cmd, 5, 0));
      output_high(EEPROM_CLK);   // data latches
      output_low(EEPROM_CLK);    // back to idle
   }   
   output_high(EEPROM_SELECT);   
   delay_ms(3);                  // tPP
}

BYTE read_ext_eeprom(EEPROM_ADDRESS address)
{
   BYTE cmd[4], i, data;
   
   cmd[0] = (BYTE) address;
   cmd[1] = (BYTE) (address >> 8);
   cmd[2] = (BYTE) (address >> 16);
   cmd[3] = 0x03;                   //(Read Data 03H)
   
   // Wait until the eeprom is done with a previous write
   while(!ext_eeprom_ready());
   
   output_low(EEPROM_SELECT);   
   for(i=0; i<32; ++i)
   {
      output_bit(EEPROM_DI, shift_left(cmd, 4, 0));
      output_high(EEPROM_CLK);   // data latches
      output_low(EEPROM_CLK);    // back to idle
   }
   
   for(i=0; i<8; ++i)
   {
      output_high(EEPROM_CLK);
      shift_left(&data, 1, input(EEPROM_DO));
      output_low(EEPROM_CLK);    // data latches & back to idle
   }   
   output_high(EEPROM_SELECT);   
   return(data);
}
//-----------------------------------------------------------------------





Testado com uma 25Q64 B/FV (3.3).
Avatar do usuário
vtrx
Dword
 
Mensagens: 1965
Registrado em: 20 Abr 2008 21:01

Re: Usando w25q32 com 18Fxx

Mensagempor vtrx » 06 Jun 2020 17:08

Rodrigo_P_A escreveu:Essas memórias são baratas mas veja o principal: você não consegue escrever somente um byte nela, só consegue escrever em blocos, então se vc quer escrever byte a byte, você tem que criar algum algorítimo e vai usar RAM pra isso, pelo menos a quantidade do SETOR, cada setor tem 4KB , e pelo que eu lembro esses PICs tem pouca RAM, ou seja, vocẽ num vai conseguir alterar só um byte, pois para isso você teria que ler um setor interno para a RAM, modificar, apagar o setor, e regravar. basicamente é isso. Pense bem


Só para encher linguiça um pouco.
Sim,estas memórias são baratas mesmo.
É possível escrever só um bytes,mas desde que o o byte na memória esteja 'zerado'($FF).
É possível não usar RAM,utilizando um setor para isso.
Quanto maior a capacidade deste memória,maior o tempo de apagamento da memória toda(mesmo que isso seja feito pelo Hardware interno da memória com um comando).
Descobri que dependendo da letra final depois do código da memória ,indica a tensão de trabalho,1.8,3.0 e 3.3,mesmo sendo 25Qxx.
A gravação destas memórias,mesmo sendo byte a byte,é extremamente rápida.
Avatar do usuário
vtrx
Dword
 
Mensagens: 1965
Registrado em: 20 Abr 2008 21:01

Re: Usando w25q32 com 18Fxx

Mensagempor Rodrigo_P_A » 07 Jun 2020 13:42

vtrx escreveu:
Rodrigo_P_A escreveu:Essas memórias são baratas mas veja o principal: você não consegue escrever somente um byte nela, só consegue escrever em blocos, então se vc quer escrever byte a byte, você tem que criar algum algorítimo e vai usar RAM pra isso, pelo menos a quantidade do SETOR, cada setor tem 4KB , e pelo que eu lembro esses PICs tem pouca RAM, ou seja, vocẽ num vai conseguir alterar só um byte, pois para isso você teria que ler um setor interno para a RAM, modificar, apagar o setor, e regravar. basicamente é isso. Pense bem


Só para encher linguiça um pouco.
Sim,estas memórias são baratas mesmo.
É possível escrever só um bytes,mas desde que o o byte na memória esteja 'zerado'($FF).
É possível não usar RAM,utilizando um setor para isso.
Quanto maior a capacidade deste memória,maior o tempo de apagamento da memória toda(mesmo que isso seja feito pelo Hardware interno da memória com um comando).
Descobri que dependendo da letra final depois do código da memória ,indica a tensão de trabalho,1.8,3.0 e 3.3,mesmo sendo 25Qxx.
A gravação destas memórias,mesmo sendo byte a byte,é extremamente rápida.


Eu sei que é possível escrever somente um byte, na verdade vc pode escrever 0 nela, ou seja, qdo vc apagar um setor , ele vai ficar todo com 0xff, aí vc pode escrever bits 0, mas num pode escrever bits 1, para voltar a 1 só apagando o setor.

dependendo da aplicação, você tem que copiar todo o setor para a RAM ou para outra área da flash para fazer um técnica de alterar somente um byte, e isso leva tempo.

Além disso , se for para log tem que usar outro tipo de técnica pois memórias flash não gostam de ficar sendo apagadas e escritas toda hora

são somente essas considerações.
---
Avatar do usuário
Rodrigo_P_A
Dword
 
Mensagens: 2097
Registrado em: 12 Out 2006 18:27
Localização: Osasco - S.P - Brasil

Re: Usando w25q32 com 18Fxx

Mensagempor vtrx » 07 Jun 2020 16:01

Segundo o datasheet,ele suporta mais de 100.000 escrita/apagamentos,o mesmo de uma Eeprom 24C512.
Uma parte dela usaria para gravar números discados de um telefone,mas não constantemente,o resto não precisaria ser regravado,mas vai armazenar audio.
Não seria uma boa opção,pois o problema é o espaço do áudio.
Não pretendo usar SDcard por motivos de manutenção,pois daria brecha para alteração desastrosas facilmente.
Avatar do usuário
vtrx
Dword
 
Mensagens: 1965
Registrado em: 20 Abr 2008 21:01

Re: Usando w25q32 com 18Fxx

Mensagempor rafael » 27 Jun 2020 17:51

Rodrigo_P_A escreveu:Essas memórias são baratas mas veja o principal: você não consegue escrever somente um byte nela, só consegue escrever em blocos, então se vc quer escrever byte a byte, você tem que criar algum algorítimo e vai usar RAM pra isso, pelo menos a quantidade do SETOR, cada setor tem 4KB , e pelo que eu lembro esses PICs tem pouca RAM, ou seja, vocẽ num vai conseguir alterar só um byte, pois para isso você teria que ler um setor interno para a RAM, modificar, apagar o setor, e regravar. basicamente é isso. Pense bem
Amigo, você está enganado. Eh possível ler e escrever 1 byte nessa memória. O problema dela (como de qualquer flash) eh o apagamento em blocos. No caso dessa memória o mínimo eh 4K.


Enviado do meu iPhone usando Tapatalk
/***************************************
Rafael Gebert

TEWAC Tecnologia
e-mail: rafael@tewac.com.br
***************************************/
rafael
Nibble
 
Mensagens: 64
Registrado em: 08 Mar 2007 10:37
Localização: Rio Grande, RS - Brazil

Voltar para PIC

Quem está online

Usuários navegando neste fórum: Nenhum usuário registrado e 1 visitante