¿porqué en tu proyecto del ADC no inicia desde 0 la visualización por el puerto B? y ¿por qué no se va incrementando de a 1 en 1?, ¿es acaso por la resolución?, bueno, de todas formas gracias, lo voy a checar, ya que necesito hacer algo usando el protocolo SPI, gracias.
Gracias de todas formas...
;*********************** Registro de control *************************************
status equ 03h
porta equ 05h
portb equ 06h
portc equ 07h
portd equ 08h
porte equ 09h
intcon equ 0bh
pir1 equ 0ch
sspbuf equ 13h
sspcon equ 14h
adcon0 equ 1fh
adresh equ 1eh
trisa equ 85h
trisb equ 86h
trisc equ 87h
trisd equ 88h
trise equ 89h
pie1 equ 8ch
sspstat equ 94h
adresl equ 9eh
adcon1 equ 9fh
;******************************* Registro de usuario ****************************
bandera equ 20h
lectura equ 21h
loop1 equ 22h
loop2 equ 23h
;******************************* Empieza el programa ***************************
list p = 16f877
org 00
goto inicio
org 04
goto inter
;****************************** Rutina que controla las interrupciones ********
inter btfsc pir1,6 ; Pregunta si hubo interrupción por fin
; De conversión A/D
goto convierte
retfie ; Si no hubo interrupción sale de la
; Interrupción
;************* Rutina de atención de interrupción de la conversión A/D *****
convierte
bcf pir1,6 ; Se limpia la bandera de interrupción
movlw d'1'
movwf bandera ; Se pone bandera en 1 para indicar
; Que hubo conversión A/D
movf adresh,0
movwf lectura ; Se leé el valor de la conversión a 8
movwf sspbuf ; Bits se traspasa el valor al registro
; SSPBUF para ser transmitido
retfie ; Sale de la interrupción
;***************************** Rutina de unos microsegundo *******************
retar movlw d'255'
movwf loop1
movlw d'100'
movwf loop2
decfsz loop2,1
goto $-1
decfsz loop1,1
goto $-5
return
;****************************** Rutina principal MAIN() *************************
inicio bcf status,6
bsf status,5 ; Banco 1
movlw b'11111111'
movwf trisb ; Puerto B como entradas digitales
movlw b'11010111'
movwf trisc ; Se configura RC3/SCK como salida,
; RC4/SDI como entrada y
; RC3/SDO como salida
movlw b'11111111'
movwf trisa
movwf trisd
movwf trise ; Puertos A,C,D y E como entradas
; Digitales
clrf adresl ; Se Limpia inicialmente la conversión
movlw b'00000001'
movwf adcon1 ; Se configura el adcon1 para que
; Todas los canales sean
; Entradas análogas y RA3 como Vref+
movlw b'11000000'
movwf sspstat ; Se configura el modo SPI para
; Muestrear al final del Impulso del
; Reloj
movlw b'01000000'
movwf pie1 ; Se activo la interrupción por fin de
; Conversión A/D
bcf status,5 ; Banco 0
clrf portb
clrf lectura
clrf adresh ; Se inicializan todos los registros que
; Se van a trabajar
movlw b'11000000'
movwf intcon ; Se activa la interrupción Global y la
; De periféricos
movlw b'00100000'
movwf sspcon ; Se activa el modo SPI en modo
; Maestro con reloj Fosc/4
movlw b'10000001'
movwf adcon0 ; Se Configura el canal 0 y se activa el
; Inicio de la conversión A/D
bsf adcon0,2
repite
movf bandera,0 ; Se pasa bandera a W
xorlw d'1' ; Comparo si son iguales
btfss status,2
goto repite
clrf bandera
call retar ; Una pequeña rutina de tiempo para
; Volver a iniciar la conversión
bsf adcon0,2 ; Inicia nuevamente la conversión
goto repite ; Bucle infinito
end
Código para el esclavo en el esamblador:
;*********************** Registro de control *************************************
status equ 03h
porta equ 05h
portb equ 06h
portc equ 07h
portd equ 08h
porte equ 09h
intcon equ 0bh
pir1 equ 0ch
sspbuf equ 13h
sspcon equ 14h
trisa equ 85h
trisb equ 86h
trisc equ 87h
trisd equ 88h
trise equ 89h
pie1 equ 8ch
sspstat equ 94h
;******************************* Registro de usuario ****************************
lectura equ 40h ; Variable que contiene el valor
; Recibido por la
; Comunicación SPI
;******************************* Empieza el programa ***************************
list p = 16f877
org 00
goto inicio
org 04
goto inter
;******************** Rutina que controla las interrupciones ******************
inter btfsc pir1,3 ; Pregunta si hubo interrupción por la
; Puerta serie síncrona
goto recibe
retfie ; Si no hubo interrupción sale de la
; interrupción
;************** Rutina de atención de interrupción de la serie sincrona ******
recibe
movf sspbuf,0
movwf lectura ; Se leé el byte recibido
movwf portb
bcf pir1,3 ; Se inicializa la interrupción
bcf sspcon,7 ; Se limpia el bit WCOL si hubo una
; Interrupción
retfie ; Retorna al PCL + 1
;****************************** Rutina principal MAIN() *************************
inicio bcf status,6
bsf status,5 ; Banco 1
movlw b'00000000'
movwf trisb ; Puerto B como salidas digitales
movlw b'11101111'
movwf trisc ; Se configura RC3/SDO como
; Entrada, RC4/SDI como salida y
; RC5/SCK como entrada
movlw b'11111111'
movwf trisa
movwf trisd
movwf trise ; Puertos A,C,D y E como entradas
; Digitales
movlw b'11000000'
movwf sspstat ; Se configura el modo SPI para
; Muestrear al final del Impulso del
; Reloj
movlw b'00001000'
movwf pie1 ; Interrupción por el módulo serie
; Síncrono habilitado
bcf status,5 ; Banco 0
clrf portb
clrf lectura
movlw b'11000000'
movwf intcon ; Se activa la interrupción Global y la ; De periféricos
movlw b'00100100'
movwf sspcon ; Se activa el modo SPI en modo
; Esclavo con reloj SCK
nada goto nada ; Espera interrupción al llenarce el
; SSPBUF
end
///////////////////////////////////////////// Rutina que reinicializa la memoria ////////////////////////////////////////
int init_mmc()
{
SETUP_SPI(SPI_MASTER | SPI_H_TO_L | SPI_CLK_DIV_16 | SPI_XMIT_L_TO_H);
OUTPUT_HIGH(PIN_C2);
for(i=0; i<20; i++)
{
SPI_WRITE(0xFF); // espero a que se inicialice la memoria que van desde 8 a 10 pulso del reloj
}
OUTPUT_LOW(PIN_C2); // Activo la targeta
for(i=0; i<20; i++)
{
SPI_WRITE(0xFF); // espero a que se inicialice la memoria que van desde 8 a 10 pulso del reloj
}
SPI_WRITE(0x40);
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0x95); // Comando CMDO datos a enviar
if(mmc_respuesta(0x01)==1)
{
return 1; // Error en memoria por que se supero el tiempo
}
i = 0;
do
{
SPI_WRITE(0x41); // Envia comando hasta que de la respuesta y hasta que se cumpla el tiempo
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0xFF); // Secuencia del comando CMD1
i= i + 1;
}
while((i<250) && (mmc_respuesta(0x00)==0x01));
if(i>=250)
{
return 1; // si se supera el tiempo de respuesta no se ha inicializado bien la targeta
}
SPI_WRITE(0x50);
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0x02);
SPI_WRITE(0x00);
SPI_WRITE(0xFF); // Comando CMD16 para configurarlo de 512 bytes
delay_ms(2);
if(mmc_respuesta(0x00)==0x01)
{
return 1; // se ha inicializado incorrectamente
}
OUTPUT_HIGH(PIN_C2);
return 0; // se ha inicializado correctamente
} Buena respuesta AngelGris.
Se supone que la velocidad del modulo spi la configuro en la siguiente linea ?
SPI_CLK_DIV_16
Otra pregunta q se me hizo al ver el código es que funcion cumplen todas estas
lineas ?
SPI_WRITE(0x40);
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0x95); // Comando CMDO datos a enviar
Saludos !!
Otra pregunta q se me hizo al ver el código es que funcion cumplen todas estas
lineas ?
SPI_WRITE(0x40);
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0x95); // Comando CMDO datos a enviar
Gracias por las respuestas, me esta sirviendo muchisimo.
Finalmente voy a ir probando en el micro ya que no puedo
simularlo.
Para conectarlo fisicamente, a que pines del pic 16F877A
debo conectar cada uno de estos pines de mi dispositivo?
DOUT
SCLK
CS
DIN
IRQ
CS e IRQ son negados.
Saludos !!
Tal cual, pero a lo que voy..
Por ejemplo..
Necesito leer el dato de 2 registros distintos
sigo los siguientes pasos
- Arranco con el CS en 1
- Delay
- CS= 0
- Delay
- spi_write (valor del registro que voy a leer)
- Delay
- variable= spi_read ()
- CS=1
- Delay
- CS=0
- delay
- spi_write (valor del registro que voy a leer)
- delay
- variable2= spi_read ()
..........
........
........
.......
¿¿ Es correcto este análisis ??
do
{
SPI_WRITE(0x41); // Envia comando hasta que de la respuesta y hasta que se cumpla el tiempo
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0x00);
SPI_WRITE(0xFF); // Secuencia del comando CMD1
i= i + 1;
}
while((i<250) && (mmc_respuesta(0x00)==0x01));
if(i>=250)
{
return 1; // si se supera el tiempo de respuesta no se ha inicializado bien la targeta
}
De que hoja de datos esta sacado eso ??
No dice nada respecto a eso en el ADE7758...
En que parte configuro eso ??
Comprobado con el osciloscopio..
Con un cristal de 4 MHz y un divisor por 16 tengo
justo 250 KHz..
Puedo usar un cristal de 10 MHz y no usar divisor, por lo que
tendría 10 MHz en CK..
bit test ??
Pero no se en que registro estan y como estan ubicados ???
Y si en el mismo programa pongo...
#use standard_io (C)
y luego...
set_tris_c(16);
A cual de las dos responde el micro ??
simon21 podrias poner el programa realizado?
estoy tratando de hacer funcionar un DSPIC 30f3013 con un ADE7753 llevo varias semanas trantando de comunicarlo y no logro hacer andar el SPI, agradeceria mucho si puedes subir el programa finalizado.
has puesto bien el pin CS? es muy importante en este tipo de integrados, y por la configuracion que veo en tu programa no veo por ningun sitio accionar el pin CS. Tambien he visto en el datasheet que deberias poner SPI_XMIT_H_TO_L en vez de L_TO_H, de todas formas primero es el CS
no no, el CS lo tienes que controlar tu, antes de enviar un dato lo debes poner a 0, enviar el dato y ponerlo a 1
fijate en la pagina 6:
http://www.analog.com/static/imported-files/data_sheets/ADE7753.pdf
#include <18F14K50.h>
#device adc=8 //8 bits 256 cuentas
#FUSES INTRC_IO //High Speed Crystal/Resonator with PLL enabled
#FUSES CPUDIV2
#FUSES MCLR //Master Clear pin enabled
#FUSES NOWDT //No Watch Dog Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOLVP //No utilizamos el modo de programación con bajo voltaje, B5(PIC18) used for I/O
#FUSES NODEBUG //No usamos codigo para debuguear
#use delay(clock=8MHz)
#define VMAX 255.00
#define AN1M 127.00
#define AN2M 127.00
#define AN_DERECHA 128
#define AN_IZQUIERDA 127
#define AN_ADELANTE 128
#define AN_ATRAS 127
#define SS PIN_B7
int8 AN1=0, AN2=0, V1, V2, direccion=0; // para atras 1
int1 adq=0;
float Vo1, Vd1, Vi1;
float Vo2, Vd2, Vi2;
////////////////////////////////////////////////////////////////////////////////
////////// INTERRUPCIONES //////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
#int_TIMER0
void TIMER0_isr(void)
{
set_timer0(15536); // 50ms
adq=1;
output_toggle(PIN_C1); // solo para chequeo en simulacion u operación
}
////////////////////////////////////////////////////////////////////////////////
////////// FUNCIONES ///////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
void adq_pote(void)
{
set_adc_channel(7); // desplazamiento longitudinal
delay_us(10);
AN1 = read_adc();
set_adc_channel(8); // desplazamiento lateral
delay_us(10);
AN2 = read_adc();
}
void calc_vel(void)
{
V1=AN1; //calculo simplificado
V2=AN2;
}
void send(void)
{
output_low(SS);
spi_write(V1);
delay_us(10);
spi_write(V2);
delay_us(10);
spi_write(direccion);
delay_us(10);
output_high(SS);
}
////////////////////////////////////////////////////////////////////////////////
////////// PROGRAMA PRINCIPAL //////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
void main()
{
set_tris_b(0b00011111);
set_tris_c(0b01001101);
setup_adc_ports(sAN7|sAN8|VSS_VDD);
setup_adc(ADC_CLOCK_INTERNAL);
setup_spi(SPI_MASTER|SPI_CLK_DIV_16|SPI_XMIT_H_TO_L|SPI_SCK_IDLE_LOW);
setup_timer_0(T0_INTERNAL);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
set_timer0(0);
enable_interrupts(INT_TIMER0);
enable_interrupts(GLOBAL);
output_high(PIN_C2);
output_high(PIN_B5);
output_high(SS);
while(TRUE)
{
if(adq==1) // se genero la interrupcion teporizada
{
disable_interrupts(GLOBAL);
adq_pote();
calc_vel();
send(); // se envian los valores de Vel al esclavo
adq=0;
enable_interrupts(GLOBAL);
}
}
}#FUSES NOPROTECT //Code not protected from reading
#FUSES NOLVP //No utilizamos el modo de programación con bajo voltaje, B5(PIC18) used for I/O
#FUSES NODEBUG //No usamos codigo para debuguear
#FUSES NOPBADEN //PORTB pins are configured as digital I/O on RESET
#FUSES CPUDIV2 //System Clock by 2
#use delay(clock=8MHZ)
#define IN1 PIN_C0
#define IN2 PIN_C2 //CPP1 PWM
#define IN3 PIN_A6
#define IN4 PIN_C1 //CPP2 PWM
#define ENA PIN_E2
#define ENB PIN_E1
#define LED PIN_D2
int8 duty1, duty2, direccion;
int8 set=0;
#int_SSP
void SSP_isr(void)
{
disable_interrupts(global);
duty1=spi_read();
while(!spi_data_is_in());
duty2=spi_read();
while(!spi_data_is_in());
direccion=spi_read();
set=1;
output_toggle(LED); // SOLO PARA CHEQUEAR QUE ENTRO EN LA INTERRUPCION
clear_interrupt(int_ssp);
enable_interrupts(global);
}
////////////////////////////////////////////////////////////////////////////////
////////// PROGRAMA PRINCIPAL //////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
void main()
{
set_tris_A(0b10111111);
set_tris_B(0b11);
set_tris_C(0b01101000);
set_tris_E(0b11111001);
set_tris_D(0b000);
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_timer_0(RTCC_OFF);
setup_timer_1(T1_INTERNAL | T1_DIV_BY_1); //genera los ticks que miden el pulso
setup_timer_2(T2_DIV_BY_1, 255, 1); //modulacion de frecuencia del PWM
setup_CCP1(CCP_PWM);
setup_CCP2(CCP_PWM);
setup_spi(SPI_SLAVE||SPI_XMIT_H_TO_L|SPI_SCK_IDLE_LOW);
output_high(IN1);
output_high(IN3);
set_pwm1_duty(150);
set_pwm2_duty(150);
clear_interrupt(int_ssp);
enable_interrupts(int_ssp);
enable_interrupts(global);
output_high(LED);
while (TRUE)
{
if(set==1)
{
disable_interrupts(global);
if(direccion==0)
{
output_high(IN1);
output_high(IN2);
set_pwm1_duty(255-duty1);
set_pwm2_duty(255-duty2);
}
if(direccion==1)
{
output_low(IN1);
output_low(IN2);
set_pwm1_duty(duty1);
set_pwm2_duty(duty2);
}
set=0;
enable_interrupts(global);
}
}
} if(set==1)
{
disable_interrupts(global);
if(direccion==0)
{
output_high(IN1);
output_high(IN2);
set_pwm1_duty(255-duty1);
set_pwm2_duty(255-duty2);
}
if(direccion==1)
{
output_low(IN1);
output_low(IN2);
set_pwm1_duty(duty1);
set_pwm2_duty(duty2);
}
set=0;
enable_interrupts(global);
} setup_spi(SPI_MASTER|SPI_CLK_DIV_16|SPI_XMIT_H_TO_L|SPI_SCK_IDLE_LOW);|SPI_XMIT_H_TO_LHola companeros.
Tome el ejemplo que pusieron pero surge que al copilarlo siempre tira el mismo erro.
Alguien me pudiera ayudar con esta lio.
Saludos después de mucho estudio, parciales, trabajo y demás cosas que se hacen en diciembre.... :D :D :D, me he puesto a trabajar con los micros ahora estoy trabajando con el modulo SPI y estado trabajando leyendo mucho realizando pruebas (por ahora simulaciones), y debido a este trabajao hoy quiero compartir con ustedes un pequeño trabajo el cual utliza dos micros 16f877 y se comunican por el protocolo SPI uno actua como maestro y el otro como esclavo, el programa hace lo siguiente.
El micro maestro: Le envia los siguientes datos al esclavo ({ 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7c, 0x07, 0x7f, 0x67}) que para un display de cátodo comú serian los siguiente (0,1,2,3,4,5,6,7,8,9) y el micro esclavo recibe los datos y los visualiza por el puerto B.
Acá les dejo la simulación y el código hay dos carpetas la primera prueba2 contiene el .hex del esclavo y prueba 1 que contiene el código, la simulación y el .hex del maestro. Espero que le agrade el ejemplo
Saludos
excelente paRCE ME AYUDASTES DEMASIADO MUCHAS GRACIAS
#include "mother.h"
int in_data[4] ;
#int_RDA
void RDA_isr(void)
{
}
void main()
{
setup_adc_ports(NO_ANALOGS|VSS_VDD);
setup_adc(ADC_CLOCK_DIV_2);
setup_spi(SPI_MASTER|SPI_L_TO_H|SPI_CLK_DIV_4);
setup_wdt(WDT_OFF);
setup_timer_0(RTCC_INTERNAL);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
enable_interrupts(INT_RDA);
disable_interrupts(GLOBAL);
OUTPUT_LOW(PIN_B2); // slave select
while(1)
{
in_data[0] = spi_read(0xff);
delay_ms(100);
}
}#include "driver.h"
int in_data[4] ,out_data[4] = {0xfa,0x06,0x07,0xfb} ;
#int_SSP //interrupcion SPI
void SSP_isr(void)
{
in_data[0] = spi_read(0xdd);
}
void main()
{
setup_adc_ports(NO_ANALOGS|VSS_VDD);
setup_adc(ADC_CLOCK_DIV_2);
setup_spi(SPI_SLAVE);
setup_wdt(WDT_OFF);
setup_timer_0(RTCC_INTERNAL);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
enable_interrupts(INT_SSP);
enable_interrupts(GLOBAL);
//Setup_Oscillator parameter not selected from Intr Oscillator Config tab
while(1)
{
}
}in_data[0] = spi_read(0xff);
in_data[0] = spi_write(0xff);in_data[0] = spi_read(0xdd);
in_data[0] = spi_read();us archivos es lo primero que baje pero en ellos no se encuentran el proyecto proteus, a menos que tenga que modificar algun archivo proteus me pide extension .pdsprj
No es fiable con delays-cortos (y a my me combienen que nisiquiera existan)
Como siempre hay un problema spi_write(mony); mony=spi_read(); no sirven para embiar variables "long" que es lo que es mony
#include<pic16f877.h>