Re: PIC 2 PIC Master/Slave Communication using I2C... Enjoy
Posted: 02 Mar 2012 09:07
my single pic i2c master and 5 slaves are working fine.
http://youtu.be/SEOJJxSO-wU
http://youtu.be/SEOJJxSO-wU
Development Tools, Compilers, Books
https://forum.mikroe.com/
programmer5 wrote:my single pic i2c master and 5 slaves are working fine.
http://youtu.be/SEOJJxSO-wU
Code: Select all
/***********************
*TÁJÉKOZÓDÁSI STRATÉGIA*
* ÉS IRÁNYÍTÓ ESZKÖZ *
* FEJLESZTÉSE *
*LÁTÁSSÉRÜLTEK SZÁMÁRA *
* PIC16f1823 @ 32MHz *
* 2013 Erdélyi Viktor *
* MASTER *
***********************/
// Slave address
const Slave = 0x69;
// 8 bit variables
typedef unsigned char uint8;
// flags
bit oldstate;
bit echoold;
// Variables
uint8 Dist1; //Distance and azimuth variables
uint8 Pot1;
uint8 Pot2;
uint8 Dist2;
uint8 Pitch;
// denominate I/O bits
sbit Echo at RC2_bit;
sbit Echo_d at TRISC2_bit;
sbit Trig at RA2_bit;
sbit Trig_d at TRISA2_bit;
void Tone1() {
Sound_Play(500, 20); // Frequency = 659Hz, duration = 1000ms
//Sound_Play(Pitch, 20); // Uncomment to modulate pitch
}
void hardinit(void) {
ANSELA = 0; // Configure AN pins as digital
ANSELC = 0;
C1ON_bit = 0; // Disable comparators
C2ON_bit = 0;
APFCON = 0b10000100;
Echo_d = 1; // Init I/O ports
Trig_d = 0;
Trig = 0;
UART1_Init(9600); // Initialize UART module at 9600 bps
Delay_ms(100); // Wait for UART module to stabilize
Sound_Init(&PORTC, 4); // Init sound
PWM1_Init(25000); // Initialize PWM1 module at 25KHz
PWM1_Start(); // Start PWM1
oldstate = 0; // Init flags
echoold = 0;
Dist1 = 0; // Initialize variables
Dist2 = 250;
Pot1 = 0;
Pot2 = 0;
Pitch = 400;
}
void send(unsigned short send_data){ // Sub for triggering slave
I2C1_Init(100000);
I2C1_Start();
I2C1_Wr(Slave);
I2C1_Wr(0xFF);
I2C1_Stop();
}
unsigned short read(){ // Sub for data request
unsigned short read_data;
I2C1_Init(100000);
I2C1_Start();
I2C1_Wr(Slave + 1);
Dist2 = I2C1_Rd(0);
Pot1 = I2C1_Rd(0);
Pot2 = I2C1_Rd(0);
delay_ms(100);
I2C1_Stop();
return read_data;
}
void distM(void) { // Subroitune for distance measuring
Dist2 = 255;
echoold = 0;
oldstate = 0;
Trig = 1;
oldstate = 1;
delay_us(11);
Trig = 0;
if (oldstate == 1){
while (echoold == 0){
if (Echo == 1){
echoold = 1;
while (Echo == 1) {
delay_us(100); // 17 mm precision
Dist2 --;
//Pitch = Dist2*5+400; // +17 mm => +5 Hz (uncomment to modulate Pitch)
}
}
}
}
}
void main() {
hardinit();
while(1) {
send; // Send trigger to slave
distM(); // Measuring distance
PWM1_Set_Duty(dist2); // Set volume
Tone1();
//read; // Request data from slave
//UART1_Write(Dist1); // Data transmission to PC
UART1_Write(Dist2);
//UART1_Write(Pot1);
//UART1_Write(Pot2);
}
}
Code: Select all
/***********************
*TÁJÉKOZÓDÁSI STRATÉGIA*
* ÉS IRÁNYÍTÓ ESZKÖZ *
* FEJLESZTÉSE *
*LÁTÁSSÉRÜLTEK SZÁMÁRA *
* PIC16f1823 @ 32MHz *
* 2013 Erdélyi Viktor *
* SLAVE *
***********************/
// Set I2C parameters
const Slave = 0x69; // Set I2C device address
const Delay_Time = 250; // Port check delay
unsigned short j; // just dummy for buffer read
unsigned short rxbuffer;
unsigned short tx_data;
// 8 bit variables
typedef unsigned char uint8;
typedef unsigned int uint16;
// flags
bit oldstate;
bit echoold;
// Variables
uint8 Dist1; //Distance and azimuth variables
uint8 Pot1;
uint8 Pot2;
uint8 Pitch;
uint16 ADC0;
uint16 ADC1;
// denominate I/O bits
sbit Echo at RC2_bit;
sbit Echo_d at TRISC2_bit;
sbit Trig at RA2_bit;
sbit Trig_d at TRISA2_bit;
sbit LED at RC3_bit;
sbit LED_d at TRISC3_bit;
void Tone1() {
Sound_Play(500, 20); // Frequency = 500Hz, duration = 20ms
//Sound_Play(Pitch, 20); // Uncomment to modulate pitch
}
void hardinit(void) {
ANSELA = 0b00000011; // Configure AN pins as digital, expect AN0 and AN1
ANSELC = 0;
C1ON_bit = 0; // Disable comparators
C2ON_bit = 0;
SSPCON = 0x36; // Set to I2C slave with 7-bit address
PIE1.SSP1IF = 1; // enable SSP interrupts
SSPADD = Slave;
INTCON = 0xC0; // enable INTCON.GIE
APFCON = 0b10000100;
Echo_d = 1; // Init I/O ports
Trig_d = 0;
Trig = 0;
Sound_Init(&PORTC, 4); // Init sound
PWM1_Init(25000); // Initialize PWM1 module at 25KHz
PWM1_Start(); // Start PWM1
ADC_Init(); // ADC init
oldstate = 0; // Init flags
echoold = 0;
Dist1 = 0; // Initialize variables
Pot1 = 0;
Pot2 = 0;
Pitch = 400;
LED_d = 0;
LED = 0;
}
void interrupt(){ // I2C slave interrupt handler
if (PIR1.SSP1IF == 1){ // I2C Interrupt
PIR1.SSP1IF = 0; // reset SSP interrupt flag
LED=1; // Just to see interrupt
//transmit data to master
if (SSPSTAT.b2 == 1){ // Read request from master
SSPBUF = tx_data; // Get data to send
SSPCON.CKP = 1; // Release SCL line
j = SSPBUF; // That's it
return;
}
if (SSPSTAT.BF == 0){ // all done,
j = SSPBUF; // Nothing in buffer so exit
return;
}
//recieve data from master
if (SSPSTAT.b5 == 1){ // Data [not address]
rxbuffer = SSPBUF; // get data
j = SSPBUF; // read buffer to clear flag [address]
return;
}
}
j = SSPBUF; // read buffer to clear flag [address]
}
void adcread(void){ // Reading ADC values, converting into 8 bit format
ADC0 = ADC_Read(0); // reading 10-bit value from ADC
ADC1= ADC_Read(1);
Pot1 = ADC0 >> 2; // writeing significant 8 bit to variable
Pot2 = ADC1 >> 2;
}
void distM(void) { // Subroitune for distance measuring
Dist1 = 255;
echoold = 0;
oldstate = 0;
Trig = 1;
oldstate = 1;
delay_us(11);
Trig = 0;
if (oldstate == 1){
while (echoold == 0){
if (Echo == 1){
echoold = 1;
while (Echo == 1) {
delay_us(100); // 17 mm precision
Dist1 --;
//Pitch = Dist2*5+400; // +17 mm => +5 Hz (uncomment to modulate Pitch)
}
}
}
}
}
void main() {
hardinit();
while(1) {
if (rxbuffer == 0xFF){
adcread(); // Reading ADC channels
distM(); // Measuring distance
PWM1_Set_Duty(Dist1); // Set volume
Tone1(); // Play Tone
}
}
}
Code: Select all
//1.============================================================================
// PRÁCTICA: Comunicación I2C Master_Slave.c
// AUTORES: Francisco Ortiz O.
// FECHA: 02-Mayo-2014
// DESCRIPCIÓN: El siguiente programa realiza la comunicación I2C entre dos
// microcontroladores. Esta parte del código configura al micro_
// controlador PIC18F4550 como MAESTRO, el cual se comunicará con
// un microcontrolador PIC16F877A que se encuentra configurado
// como ESCLAVO. Enviamos el estado de un potenciómetro conectado
// en el canal analógico A0 del MAESTRO, y al presionar el pul_
// sante conectado en RA1 enviado las letras "UPS" secuencialmente.
//==============================================================================
//2. ARCHIVOS DE CABECERA
//==============================================================================
// 3.===========================================================================
// DECLARACIÓN DE VARIABLES GLOBALES.
//==============================================================================
unsigned int lectura;
// 4.===========================================================================
// DECLARACIÓN DE PROTOTIPOS DE PROCEDIMIENTOS Y FUNCIONES.
//==============================================================================
void escribir_Pic(unsigned int address,
unsigned int send_data); // Escribe al ESCLAVO
unsigned short leer_Pic(); // Lee datos del ESCLAVO
void Init_Perifericos(); //Iniciliza el PIC
// 5.===========================================================================
// DEFINICIÓN DE PROCEDIMIENTOS Y FUNCIONES DE LAS INTERRUPCIONES.
//==============================================================================
// 6.===========================================================================
// DEFINICIÓN DEL PROCEDIMIENTO DE ATENCIÓN A LAS INTERRUPCIONES.
//==============================================================================
// 7.===========================================================================
// DEFINICIÓN DE PROCEDIMIENTOS Y FUNCIONES DEL PROGRAMA PRINCIPAL.
//==============================================================================
void escribir_Pic(unsigned int address, unsigned int send_data){
I2C1_Start(); //Inicia Bus I2C
I2C1_Wr(0xB0); //Envía dirección del ESCLAVO (dirección + W)
I2C1_Wr(address); //Envía dirección de almacenamiento en el ESCLAVO
I2C1_Wr(send_data); //Envía el dato a escribir en el ESCLAVO
I2C1_Stop(); //Detiene Bus I2C
delay_ms(50);
}
unsigned short leer_Pic(){
unsigned short read_data;
I2C1_Start(); //Inicia Bus I2C
I2C1_Wr(0xB1); //Envía dirección del ESCLAVO (dirección + R)
read_data = I2C1_Rd(0);
delay_ms(100);
I2C1_Stop(); //Detiene Bus I2C
return read_data;
}
void Init_Perifericos(){
ADCON1 = 0x0E; // RA0 como entrada analógica, RA1-RA6 Digitales
CMCON = 0b00000111; // Deshabilita comparadores
INTCON2 = 0x80; // Deshabilita pull up en el puerto B
// clears internal latches
LATA = 0xFF;
LATC = 0x00;
LATD = 0x00;
LATE = 0x00;
TRISA = 0xFF;
TRISB = 0x00;
TRISC = 0x00;
TRISD = 0x00;
TRISE = 0x00;
}
// 8.===========================================================================
// DEFINICIÓN DEL PROGRAMA PRINCIPAL.
//==============================================================================
void main(){
bit oldstate,oldstate1;
Init_Perifericos();
ADC_Init();
I2C1_Init(100000); //Inicializar Bus I2C a 100kHz
delay_ms(500);
while (1){
lectura = ADC_Read(0)/4; //Obtener una lectura de 8bits
escribir_Pic(4,lectura); //Escribimos al ESCLAVO
if (Button(&PORTA, 1, 1, 1)) { // Detect logical one
oldstate = 1; // Update flag
}
if (oldstate && Button(&PORTA, 1, 1, 0)) { // Detect one-to-zero transition
escribir_Pic(1,0x55); //Escribimos una "U" al esclavo
delay_ms(20);
escribir_Pic(2,0x50); //Escribimos una "P" al esclavo
delay_ms(20);
escribir_Pic(3,0x53); //Escribimos una "S" al esclavo
oldstate = 0; // Update flag
}
}
}
Code: Select all
//1.============================================================================
// PRÁCTICA: Comunicación I2C Master_Slave.c
// AUTORES: Francisco Ortiz O.
// FECHA: 02-Mayo-2014
// DESCRIPCIÓN: Este código se encarga de configurar al
// microcontrolador PIC16F877A como esclavo para que atienda las
// interrupciones generadas por el maestro; que es un microcon_
// trolador PIC18F4550 y atiende solo a la dirección 0xB0.
// Realizamos la lectura del estado de un potenciómetro conectado
// en el maestro y mostramos los datos en un LCD 2x16.
//==============================================================================
//2. ARCHIVOS DE CABECERA
//==============================================================================
sbit LCD_RS at RD2_bit;
sbit LCD_EN at RD3_bit;
sbit LCD_D4 at RD4_bit;
sbit LCD_D5 at RD5_bit;
sbit LCD_D6 at RD6_bit;
sbit LCD_D7 at RD7_bit;
sbit LCD_RS_Direction at TRISD2_bit;
sbit LCD_EN_Direction at TRISD3_bit;
sbit LCD_D4_Direction at TRISD4_bit;
sbit LCD_D5_Direction at TRISD5_bit;
sbit LCD_D6_Direction at TRISD6_bit;
sbit LCD_D7_Direction at TRISD7_bit;
// 3.===========================================================================
// DECLARACIÓN DE VARIABLES GLOBALES.
//==============================================================================
unsigned char rxbuffer,address,buff,dato, direccion;
unsigned short tx_data;
int a=0;
// 4.===========================================================================
// DECLARACIÓN DE PROTOTIPOS DE PROCEDIMIENTOS Y FUNCIONES.
//==============================================================================
void initPerifericos();
unsigned short BcdToShort( unsigned short bcd );
unsigned short ShortToBcd( unsigned short valor);
// 5.===========================================================================
// DEFINICIÓN DE PROCEDIMIENTOS Y FUNCIONES DE LAS INTERRUPCIONES.
//==============================================================================
// 6.===========================================================================
// DEFINICIÓN DEL PROCEDIMIENTO DE ATENCIÓN A LAS INTERRUPCIONES.
//==============================================================================
void interrupt(){
if (PIR1.SSPIF){ //Comprueba si la interrupción es por I2C
PIR1.SSPIF = 0; //Apagamos la bandera SSP
if(!SSPSTAT.R_W & SSPSTAT.D_A & SSPSTAT.BF ){
a++;
PORTB=2;
if (a==1){
address=SSPBUF; //Guardamos la dirección de almacenamiento
} //del dato recibido.
if (a==2){
rxbuffer=SSPBUF; //Guardamos el dato recibido
a=0;
}
PIR1.SSPIF = 0; //Apagamos la bandera SSP
}
if( !SSPSTAT.R_W & !SSPSTAT.D_A & SSPSTAT.BF ){
buff = SSPBUF;
PIR1.SSPIF = 0;
}
}
}
// 7.===========================================================================
// DEFINICIÓN DE PROCEDIMIENTOS Y FUNCIONES DEL PROGRAMA PRINCIPAL.
//==============================================================================
void initPerifericos(){
ADCON1 = 7; // Todos los puertos como digitales
CMCON = 0b00000111; // Deshabilita comparadores
TRISA = 0; // Set PORTA as output
TRISB = 0; // Set PORTB as output
//TRISC = 0b00011000; // Set SCL y SDA como ingresos
TRISC.B3 = 1; // Set SCL (PORTC,3) pin como ingreso
TRISC.B4 = 1; // Set SDA (PORTC,4) pin como ingreso
PortB=0;
//Configuracion de interrupciones
INTCON = 0b00000000;
SSPCON = 0b00111110; // Modo esclavo 7 bits de direccion.
SSPCON2 = 0x00;
SSPADD = 0xB0; //Dirección del dispositivo
SSPSTAT=0x00;
SSPCON.SSPEN = 1;
SSPSTAT.SMP = 1;
SSPSTAT.CKE = 1;
PIR1.SSPIF = 0;
PIR2.BCLIF=0;
PIE1.SSPIE = 1; // Habilita la interrupcion del modulo SSP
INTCON.PEIE = 1; // Habilita las interrupciones de los perifericos
INTCON.GIE = 1; // Habilita las interrupciones globales!
}
unsigned short BcdToShort( unsigned short bcd ){
unsigned short LV, HV;
LV = bcd&0x0F;
HV = (bcd>>4)&0x0F;
return LV + HV*10;
}
unsigned short ShortToBcd( unsigned short valor){
unsigned short HV, LV;
HV = valor/10;
LV = valor - HV*10;
return LV + HV*16;
}
// 8.===========================================================================
// DEFINICIÓN DEL PROGRAMA PRINCIPAL.
//==============================================================================
void main(){
char as[6];
initPerifericos();
Lcd_Init(); // Initialize LCD
Lcd_Cmd(_LCD_CLEAR); // Clear LCD display
Lcd_Cmd(_LCD_CURSOR_OFF); // Turn cursor off
lcd_Out(1,1,"SLAVE");
while (1){
if (address==4){ //Si la dirección es 4 es dato del pot.
intToStr(rxbuffer,as);
lcd_out(1,10,as);
delay_ms(50);
}
if (address!= 4){ //Si es diferente de 4 mostrar datos en
dato=rxbuffer; //el LCD.
direccion=address;
lcd_chr(2,direccion,dato);
}
}
}
Plz show me the false.Remoeggel wrote:
It works now.
The problem was a false value in the register SSPCON.
Remo