Ändra i2c hastighet

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Christian
Inlägg: 86
Blev medlem: 3 november 2003, 22:54:49

Ändra i2c hastighet

Inlägg av Christian »

Hej!
Först en "dum fråga": När man pratar om hastigheten på i2c bussen ex 100kHz, menar man då frekvensen på klockan? Alltså om jag tar 1/periodtiden på klockan så får jag hastigheten?

I så fall så har jag ett följdproblem: Jag vill få upp hastigheten på bussen till 100kHz
När jag mäter på min buss med en logikanalysator så får jag cirka 20 kHz.

Jag försöker kommunicera med en kompass (hmc6352) och en PIC18F4620 med intern oscillator på 8MHz.
Jag använder Hi-Techs kompilator och deras bibliotek för i2c.

Jag bifogar koden jag använder:

Först och främst i2c.h
Här har jag ändrat (enligt databladet) så att MASTER_MODE = 0b1000 // I2C Master mode, clock = FOSC/(4 * (SSPADD + 1))
Sedan sätter jag SSPADD = 19; i main vilket borde ge mig 100kHz eftersom (8*10^6) / (100*10^3) = 4 * (SSPADD +1) <=> SSPADD = (80 / 4) - 1 = 19

Kod: Markera allt

#ifndef	_I2C_H_
#define _I2C_H_

/*
 *	SDA (data) and SCL (clock) bits
 *	
 *	Special note!!!
 *	
 *	If the clock and data lines are in the same port, you will need
 *	to beware of the Read/Modify/Write issue in the PIC - since
 *	a bit set or clear on any one bit in a port will read and write
 *	back all other bits, any bits configured as input which 
 */


/* Uncomment the next line to use the PIC's SSP Module*/
#define I2C_MODULE 1

#ifdef I2C_MODULE
/* I2C module uses PORT C */
#define SCL             RC3             /* clock on port C bit 2 */
#define SCL_DIR         TRISC3
#define SDA     RC4                     /* data on port C bit 1 */
#define SDA_DIR         TRISC4
#define I2CTRIS TRISC
//#define MASTER_MODE     0B1011          /* I2C firmware controlled Master Mode (slave idle) */
#define MASTER_MODE     0B1000          /* I2C Master mode, clock = FOSC/(4 * (SSPADD + 1)) */
#define SSPMode(val)   SSPCON1 &=0xF0; SSPCON1 |=(val & 0xf)

#else
/* Change port as required - defaults to port b */
#define	SCL		RB2		/* clock on port B bit 2 */
#define	SCL_DIR		TRISB2

#define SDA             RB1             /* data on port B bit 1 */
#define	SDA_DIR		TRISB1
#define I2CTRIS TRISB

#endif

#define M_SDA_INP	0x02
#define M_SDA_OUT   0xFD
#define M_SCL_INP   0x04
#define M_SCL_OUT	0xFB

#define I2C_INPUT	1		/* data direction input */
#define I2C_OUTPUT	0		/* data direction output */

#define I2C_READ	0x01		/* read bit used with address */
#define I2C_WRITE	0x00		/* write bit used with address */

#define FALSE		0
#define TRUE		!FALSE

#define I2C_ERROR	(-1)
#define I2C_LAST	FALSE		/* SendAck: no more bytes to send */
#define I2C_MORE	TRUE		/* SendAck: more bytes to send */

#define i2c_Start()		i2c_Restart()
#define i2c_WriteTo(address)	i2c_Open((address), I2C_WRITE)
#define i2c_ReadFrom(address)	i2c_Open((address), I2C_READ)

#ifdef I2C_MODULE
#define SCL_HIGH() SCL_DIR = I2C_INPUT
#define SCL_LOW()  SCL_DIR = I2C_OUTPUT
#define SDA_HIGH() SDA_DIR = I2C_INPUT
#define SDA_LOW()  SDA_DIR = I2C_OUTPUT
#else
#define SCL_HIGH() SCL = 1; SCL_DIR = I2C_OUTPUT
#define SCL_LOW()  SCL = 0; SCL_DIR = I2C_OUTPUT
#define SDA_HIGH() SDA = 1; SDA_DIR = I2C_OUTPUT
#define SDA_LOW()  SDA = 0; SDA_DIR = I2C_OUTPUT
#endif

/*
 * Timings for the i2c bus. Times are rounded up to the nearest
 * micro second.
 */

#define I2C_TM_BUS_FREE		5
#define	I2C_TM_START_SU		5
#define I2C_TM_START_HD		4
#define I2C_TM_SCL_LOW		5
#define	I2C_TM_SCL_HIGH		4
#define I2C_TM_DATA_SU		1
#define I2C_TM_DATA_HD          0
#define I2C_TM_SCL_TO_DATA	4	/* SCL low to data valid */
#define	I2C_TM_STOP_SU		4
//#define I2C_TM_SCL_TMO		10	/* clock time out */
#define I2C_TM_SCL_TMO		10	/* clock time out */
extern signed char	i2c_ReadAcknowledge(void);
extern unsigned char	i2c_SendAddress(unsigned char, unsigned char);
extern unsigned char	i2c_SendByte(unsigned char);
extern int		i2c_ReadByte(void);
extern void		i2c_Restart(void);
extern void		i2c_Stop(void);
extern void		i2c_SendAcknowledge(unsigned char);
extern signed char	i2c_PutByte(unsigned char);
extern int		i2c_GetByte(unsigned char);
extern unsigned char	i2c_Open(unsigned char, unsigned char);
extern unsigned char	i2c_GetString(unsigned char *, unsigned char);
extern int		i2c_PutString(const unsigned char *, unsigned char);
extern unsigned char	i2c_WaitForSCL(void);
extern void i2c_Free();
#endif			/* _I2C_H_ */
Sedan i2c.c:

Kod: Markera allt

#include	<pic18.h>
#include	"delay.h"
#include 	"i2c.h"

/*
 *	I2C functions for HI-TECH PIC C - master mode only
 */

/*
 * 	TIMING - see Philips document: THE I2C-BUS SPECIFICATION
 */


/*
 * 	Send stop condition
 * 	  - data low-high while clock high
 */

void
i2c_Stop(void)
{
	 /* don't assume SCL is high on entry */
	 /*------------------------------------------------------------------------------------*/
       //SDA_LOW();                      /* ensure data is low first */
       //SCL_HIGH();
       /*------------------------------------------------------------------------------------*/
       SCL_LOW();			// Use this line for START
       SDA_LOW();                      /* ensure data is low first */
	DelayUs(I2C_TM_DATA_SU);
	SCL_DIR = I2C_INPUT;		/* float clock high */
	DelayUs(I2C_TM_STOP_SU);
        SDA_HIGH();                     /* the low->high data transistion */
	DelayUs(I2C_TM_BUS_FREE);	/* bus free time before next start */
        SDA_DIR = I2C_INPUT;            /* float data high */

	return;
}

/*
 * 	Send (re)start condition
 * 	  - ensure data is high then issue a start condition
 * 	  - see also i2c_Start() macro
 */

void
i2c_Restart(void)
{
        SCL_LOW();                      /* ensure clock is low */
        SDA_HIGH();                     /* ensure data is high */

	DelayUs(I2C_TM_DATA_SU);

	SCL_DIR = I2C_INPUT;		/* clock pulse high */
	DelayUs(I2C_TM_SCL_HIGH);

        SDA_LOW();                      /* the high->low transition */
        DelayUs(I2C_TM_START_HD);
	return;
}

/*
 * 	Send a byte to the slave
 * 	  - returns true on error
 */

unsigned char
i2c_SendByte(unsigned char byte)
{
	signed char i;

	for(i=7; i>=0; i--)
	{
                SCL_LOW();                      /* drive clock low */
						/* data hold time = 0, send data now */
                SDA_DIR = ((byte>>i)&0x01);
                if ((byte>>i)&0x01) {           /* bit to send */
                    SDA_HIGH();
                }
                else {
                    SDA_LOW();
                }
		DelayUs(I2C_TM_DATA_SU);
		SCL_DIR = I2C_INPUT;		/* float clock high */

		if(i2c_WaitForSCL())		/* wait for clock release */
			return TRUE;		/* bus error */

		DelayUs(I2C_TM_SCL_HIGH);	/* clock high time */
	}


	return FALSE;
}

/*
 * 	send an address and data direction to the slave
 * 	  - 7-bit address (lsb ignored)
 * 	  - direction (FALSE = write )
 */

unsigned char
i2c_SendAddress(unsigned char address, unsigned char rw)
{
        return i2c_SendByte(address | (rw?1:0));
}

/*
 * 	Check for an acknowledge
 * 	  - returns ack or ~ack, or ERROR if a bus error
 */

signed char
i2c_ReadAcknowledge(void)
{
	unsigned char ack;

        SCL_LOW();                              /* make clock is low */
	SDA_DIR = I2C_INPUT;			/* disable data line - listen for ack */
	DelayUs(I2C_TM_SCL_TO_DATA);		/* SCL low to data out valid */
	SCL_DIR = I2C_INPUT;			/* float clock high */
	DelayUs(I2C_TM_DATA_SU);
	ack = SDA;				/* read the acknowledge */

	/* wait for slave to release clock line after processing byte */
	if(i2c_WaitForSCL())
		return I2C_ERROR;
	return ack;
}

/*
 * 	Read a byte from the slave
 * 	  - returns the byte, or I2C_ERROR if a bus error
 */

int
i2c_ReadByte(void)
{
	unsigned char i;
	unsigned char byte = 0;

	for(i=0; i<8; i++)
	{
                SCL_LOW();                      /* drive clock low */
		DelayUs(I2C_TM_SCL_LOW);	/* min clock low  period */
		SDA_DIR = I2C_INPUT;		/* release data line */

		SCL_DIR = I2C_INPUT;		/* float clock high */
		if(i2c_WaitForSCL())
			return I2C_ERROR;
		DelayUs(I2C_TM_SCL_HIGH);
		byte = byte << 1;		/* read the next bit */
		byte |= SDA;
	}
	return (int)byte;
}

/*
 * 	Send an (~)acknowledge to the slave
 * 	  - status of I2C_LAST implies this is the last byte to be sent
 */

void
i2c_SendAcknowledge(unsigned char status)
{
        SCL_LOW();
        if ( status & 0x01) {
            SDA_LOW();                          /* drive line low -> more to come */
        }
        else { 
            SDA_HIGH();
	}
	DelayUs(I2C_TM_DATA_SU);
	SCL_DIR = I2C_INPUT;			/* float clock high */
	DelayUs(I2C_TM_SCL_HIGH);
	return;
}

/*
 * 	Send a byte to the slave and acknowledges the transfer
 * 	  - returns I2C_ERROR, ack or ~ack
 */

signed char
i2c_PutByte(unsigned char data)
{
	if(i2c_SendByte(data))
		return I2C_ERROR;
	return i2c_ReadAcknowledge();	/* returns ack, ~ack */
}

/*
 * 	Get a byte from the slave and acknowledges the transfer
 * 	  - returns true on I2C_ERROR or byte
 */

int
i2c_GetByte(unsigned char more)
{
	int byte;

	if((byte = i2c_ReadByte()) == I2C_ERROR)
		return I2C_ERROR;

	i2c_SendAcknowledge(more);

	return byte;
}

/*
 * 	Send an array of bytes to the slave and acknowledges the transfer
 * 	  - returns number of bytes not successfully transmitted
 */

int
i2c_PutString(const unsigned char *str, unsigned char length)
{
	signed char error;

	while(length)
	{
		if((error = i2c_PutByte(*str)) == I2C_ERROR)
			return -(int)length;		/* bus error */
		else
			if(error)
				return (int)length;	/* non acknowledge */
		str++;
		length--;
	}

	return FALSE;					/* everything OK */
}

/*
 * 	Reads number bytes from the slave, stores them at str and acknowledges the transfer
 * 	  - returns number of bytes not successfully read in
 */

unsigned char
i2c_GetString(unsigned char *str, unsigned char number)
{
	int byte;

	while(number)
	{
		if((byte = i2c_GetByte(number-1)) == I2C_ERROR)
			return number;			/* bus error */
		else
			*str = (unsigned char)byte;
		str++;
		number--;
	}

	return FALSE;					/* everything OK */
}

/*
 * 	Opens communication with a device at address. mode
 * 	indicates I2C_READ or I2C_WRITE.
 * 	  - returns TRUE if address is not acknowledged
 */

unsigned char
i2c_Open(unsigned char address, unsigned char mode)
{
	i2c_Start();
	i2c_SendAddress(address, mode);
        if(i2c_ReadAcknowledge()) 
		return TRUE;

	return FALSE;
}

/*
 * 	wait for the clock line to be released by slow slaves
 * 	  - returns TRUE if SCL was not released after the
 * 	    time out period.
 * 	  - returns FALSE if and when SCL released
 */

unsigned char
i2c_WaitForSCL(void)
{
	/* SCL_DIR should be input here */

	if(!SCL)
	{
		DelayUs(I2C_TM_SCL_TMO);
		/* if the clock is still low -> bus error */
		if(!SCL)
			return TRUE;
	}
	return FALSE;
}
void
i2c_Free()
{
	unsigned char ucI;

	SDA_DIR=I2C_INPUT;
	for(ucI=0;ucI!=9;ucI++)
	{
                SCL_HIGH();
		DelayUs(5);
                SCL_LOW();
		DelayUs(5);
	}
}

unsigned char i2c_read(unsigned char ucAdr)
{
	unsigned char ucDat;

	if (i2c_ReadFrom(ucAdr)==0)
	{
		ucDat=i2c_GetByte(I2C_MORE);
		i2c_Stop();

	}

	return(ucDat);
}
och slutligen mitt huvudprogram:

Kod: Markera allt

/* I2C test program that writes & reads data to an I2C EEPROM device. */

#include <pic18.h>
#include "delay.h"
#include "i2c.h"
#include <stdlib.h>
#include <stdio.h>  
#include <stdarg.h> 
#define BAUD 4800  
#define FOSC 8000000L
//#define DIVIDER ((int)(FOSC/(16UL * BAUD) -1))// for >= 9600 baud
#define DIVIDER ((int)(FOSC/(64UL * BAUD) -1))// for < 9600 baud
#define ROM 0xA0        /* I2C EEPROM */
unsigned char buffer[5]= 0;
void  i2c_eeprom_write_byte( int , unsigned int  , char, int );
void i2c_eeprom_write_string( int , unsigned int  , char[]);
	

void usart(void){
	TRISC = 0XFF;
	TXEN = 1; 		//Allows sending
	SYNC = 0; 		//The SYNC bit should be cleared to select asynchronous operation.
	SPEN = 1; 		//SPEN bit is used to enable the entire serial port
	BRGH = 0;
	SPBRG = DIVIDER;		// 4800  
	BRG16 = 0;
	TX9 = 0;
	RX9 = 0;
	CREN = 0;
	CREN = 1; 		//Allows receiving
	GIE = 0;  		//*Interrupts
	PEIE = 0;
	TXIE = 0; 		//Disable transmit interrupt
	RCIE = 0; 		//Disable receive interrupt
}
void putch(unsigned char c){ 
	
	while(!TXIF) 	//Set when TXREG is empty
	continue; 		//Continue looping while TXREG is not available
	TXREG = c; 		//Put character to be sent onto TXREG 

}
void setup(void){
	OSCCON  = 0b01110000;	// internal osc select, 8MHz
	ADCON1 = 0xFF;			// All pins digital
	usart();
}




void main(void) {

	unsigned char count,val;
	setup();
	TRISD=0;        /* use a led on RB0 - set as output */
	PORTD=0;
	RD1=0;
	char data = 0;
	char dataString[5];
	/* initialize i2c */
	#ifdef I2C_MODULE
		SSPMode(MASTER_MODE);
	    	SSPEN = 1;
    		CKP = 1;
	#else
    		SCL_DIR = I2C_OUTPUT;
    		SDA_DIR = I2C_OUTPUT;
    		SDA = 0;
    		SCL = 0;
	#endif
	SSPADD = 19;
	int var = 0;
	char data;
	DelayMs(100);
	DelayMs(100);
	DelayMs(100);
	DelayMs(100);
	DelayMs(100);
	DelayMs(100);
	char data = 0xFF;
	i2c_WriteTo(0x42);
	i2c_PutByte('A');
	i2c_Stop();
	DelayMs(3);
	i2c_ReadFrom(0x43);
	i2c_Start();
	data = i2c_GetByte(1);
	ACKDT=0;
	ACKEN=1;
	data = i2c_GetByte(0);
	i2c_Stop();	
	while(1) {		
	}
}


Mitt program ger mig följande i logik-analysatorns output:
screenshotT1T2.png
Alltså om jag mäter en periodtid på klockan så får jag cirka 20kHz

Är det något annat jag behöver tänka på om jag ska ändra hastigheten?
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Ändra i2c hastighet

Inlägg av sodjan »

Länk till dokumentationen skulle hjälpa. Jag hittade kompilator
manualerna men där saknas info om I2C rutinerna.
Har du funderat på att fixa en liten "reproducer" med enbart det
som behövs för att testa fenomenet ? Kanske en kort assembler
rutin för att verifiera I2C hanteringen ? Eller det kanske du gjort.

Det *ser* ju rimligt ut. Värdet matchar värdet för 4 Mhz/100Khz
i databladet (d.v.s ca det dubbla).
anders_w
Inlägg: 112
Blev medlem: 6 september 2011, 17:02:03

Re: Ändra i2c hastighet

Inlägg av anders_w »

Hej

Jag har använt denna kod förrut och känner igen problemet. Det största felet är DelayUs och hur den används. Det tas ingen hänsys till tiden det tar att anropa funktionen och varje varv i delay-loopen tar längre tid än det är tänkt. Särskilt dåligt blir det på en 4 MHz-processor där antalet varv i loopen blir få. Ersätt alla anrop till DelayUs med lämpligt antal NOP om du vill optimera maximalt.
Användarvisningsbild
swesysmgr
Inlägg: 14935
Blev medlem: 28 mars 2009, 06:56:43
Ort: Göteborg

Re: Ändra i2c hastighet

Inlägg av swesysmgr »

Klockan ser konstig ut men det kanske beror på delayfelet som nämns ovan eller har du något annat på bussen som inte hinner med och stretchar klockan?
anders_w
Inlägg: 112
Blev medlem: 6 september 2011, 17:02:03

Re: Ändra i2c hastighet

Inlägg av anders_w »

Kom ihåg att en 4 MHz PIC exekverar en instruktion per mikrosekund. 100 kHz I2C låter alltså processorn utföra 10 instruktioner per databit. Några instruktioner går för att toggla klocka och data. Dessutom ska databitarna räknas och eventuellt klockan läsas (klockstretch?). Funktionsanrop och villkorat hopp i delayloopen tar dubbla instruktionstiden. Dessutom ska funktionen returnera också. Det blir svårt att hinna med...
anders_w
Inlägg: 112
Blev medlem: 6 september 2011, 17:02:03

Re: Ändra i2c hastighet

Inlägg av anders_w »

Förlåt, jag ser nu att det handlar om 8 MHz PIC. Alltså 20 instruktioner per bit. Det gör livet lite enklare, men du får inte slösa med instruktioner ändå...
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Ändra i2c hastighet

Inlägg av sodjan »

Eftersom det är hårdvaru I2C så är antalet instruktioner
mer eller mindre ointressant så länge hårdvaran hänger med.
Det som man måste hinna med är att ladda om registren...

Om det *inte* är hårdvaru I2C så bör hela designen skrotas
och göras om.
bearing
Inlägg: 11676
Blev medlem: 2 mars 2006, 01:01:45
Ort: Ängelholm

Re: Ändra i2c hastighet

Inlägg av bearing »

Eftersom att klockan är helt ojämn i bilden från logikanalysatorn är det nog gjort i mjukvara.

Med tanke på följande kodrad verkar det som att det är meningen att biblioteket ska vara generellt, d.v.s att det ska kunna använda hårdvara ifall kretsen har det, annars mjukvara. Men jag ser inte någon kod som stöder hårdvarulösningen. Verkar som att det är mjukvara i båda fallen? fast i det ena fallet bitbangas I²C-pinnarna för hårdvarumodulen?

Kod: Markera allt

/* Uncomment the next line to use the PIC's SSP Module*/
#define I2C_MODULE 1
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Ändra i2c hastighet

Inlägg av sodjan »

Raden *är* "Uncommened" !
Och man använder hårdvaruregistren i koden. Och allt annat i koden
pekar på att det ska vara hårdvaru-I2C. Rätt pinnar och rätt register.

Men, som jag sa tidigare, det saknas dokumentation för I2C_* rutinerna
för att verifiera detta. Det är mycket möjligt att utvecklingsmiljön ändå väljer att
köra mjukvaru-I2C, och de observerade fenomenen stöder ju i och för sig det...

Tja, det är väl ett exempel på "kör hårt!" utan att riktigt ha koll på hur det fungerar. :-)
bearing
Inlägg: 11676
Blev medlem: 2 mars 2006, 01:01:45
Ort: Ängelholm

Re: Ändra i2c hastighet

Inlägg av bearing »

Jag vet att raden är avkommenterad. Det jag skrev var bara att raden tyder på att biblioteket är tänkt att vara generellt, vilket även mycket annat i koden tyder på. Men det verkar som att dom bara gjort det halvfärdigt.

Kolla t.ex. funktionen i2c_SendByte. I den funktionen borde det ju rimligtvis finnas #ifdef I2C_MODULE för att kunna skilja mellan de olika fallen, men det finns det inte. Oavsett om man definierat I2C_MODULE körs alltså koden i den rutinen, vilket ser ut som vanlig bit-banging.

Kanske ske en annan variant av i2c.c användas för att få hårdvaruvarianterna av funktionerna.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Ändra i2c hastighet

Inlägg av sodjan »

OK, du har en poäng där. Jag kollade inte så långt eftersom
frågan gällde baudrate registret för hårdvaru-I2C... :roll:

Ja men då så...
Christian
Inlägg: 86
Blev medlem: 3 november 2003, 22:54:49

Re: Ändra i2c hastighet

Inlägg av Christian »

Tack för alla svar! Jag bestämde mig för att skippa biblioteksfunktionen helt eftersom mycket bara förvirrar en.. Så jag började om från scratch och skrev kod. Jag får nu 100kHz på klockan =)
Nu när jag testar koden mot ett Eeprom lyckas jag med att addressera minnet, men när jag försöker läsa direkt efter så får jag bara några få korta pulser..

Följande fungerar:

Kod: Markera allt

	   i2c_start();
		SSPBUF=0xA0;				//write
		i2c_wait();
		SSPBUF=(5 >> 8);
		i2c_wait();
		SSPBUF=(5 & 0xFF);
		i2c_wait();
		i2c_stop();
och ger följande output:
EEPROM.png
Men lägger jag till följande direkt efter så fungerar det inte..

Kod: Markera allt

i2c_start();
SSPBUF=0xA1;			//read
Är det någon flagga som måste resetas innan man gör en ny operation?


bifogar den nyskrivna koden också:

Kod: Markera allt

#include <htc.h>
#include <stdlib.h>
#include <stdio.h>  
#include <stdarg.h> 
#include <math.h>
#include "math.h"
#define BAUD 4800  
#define FOSC 8000000L
//#define DIVIDER ((int)(FOSC/(16UL * BAUD) -1))// for >= 9600 baud
#define DIVIDER ((int)(FOSC/(64UL * BAUD) -1))// for < 9600 baud

void usart(void){
	TRISC = 0XFF;
	TXEN = 1; 		//Allows sending
	SYNC = 0; 		//The SYNC bit should be cleared to select asynchronous operation.
	SPEN = 1; 		//SPEN bit is used to enable the entire serial port
	BRGH = 0;
	SPBRG = DIVIDER;		// 4800  
	BRG16 = 0;
	TX9 = 0;
	RX9 = 0;
	CREN = 0;
	CREN = 1; 		//Allows receiving
	GIE = 1;  		//*Interrupts
	PEIE = 1;
	TXIE = 0; 		//Disable transmit interrupt
	RCIE = 0; 		//Enable receive interrupt
}

void putch(unsigned char c){ 
	
	while(!TXIF) 	//Set when TXREG is empty
	continue; 		//Continue looping while TXREG is not available
	TXREG = c; 		//Put character to be sent onto TXREG 

}


void setup(void){
	OSCCON  = 0b01110000;	// internal osc select, 8MHz
	ADCON1 = 0xFF;			// All pins digital
	usart();
}

void i2c_init(void){
	TRISC3=1;					//TRISC <4:3> as inputs
	TRISC4=1;
	SSPCON1=0b00101000;			//enable MMSP module, Mastermode clock = Fosc/(4*(SSPADD + 1))	
	SSPADD=19;					//SCL frequency 100kHz
	printf("Done i2c_init");
	putch(0x0D);
}

void i2c_start(void){
SEN=1;
while(SSPIF==0) continue;
SSPIF=0;
}

void i2c_stop(void){
PEN=1;
while(SSPIF==0) continue;
SSPIF=0;
}

void i2c_wait(void){
while(SSPIF==0) continue;
SSPIF=0;
}

void main(void){
	setup();
	i2c_init();
	char data;
	while(1){
		i2c_start();
		SSPBUF=0xA0;				//write
		i2c_wait();
		SSPBUF=(5 >> 8);
		i2c_wait();
		SSPBUF=(5 & 0xFF);
		i2c_wait();
		i2c_stop();
	
	}							
}
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
bearing
Inlägg: 11676
Blev medlem: 2 mars 2006, 01:01:45
Ort: Ängelholm

Re: Ändra i2c hastighet

Inlägg av bearing »

Men lägger jag till följande direkt efter så fungerar det inte..
Vad menar du med att det inte fungerar?

Efter att du sagt åt slaven att du vill ta emot måste du väl också läsa slaven genom att sätta RCEN. Har du gjort det?

EDIT: Här finns exempelkod:
http://www.8051projects.net/i2c-twi-tut ... xample.php
Skriv svar