|
|
View previous topic :: View next topic |
Author |
Message |
Arakel
Joined: 06 Aug 2016 Posts: 107 Location: Moscow
|
A few questions about eeprom 24AA12 and 16F690 |
Posted: Fri Mar 24, 2017 2:01 pm |
|
|
I have a few questions since I am trying to interface EEPROM 24AA128 with PIC16F690.
Can someone please explain what exactly does this built-in function do, and why are there 2 options?
Code: |
i2c_write(0xa0); // Device address
i2c_write(i2c_command); // Write Command
|
The first one should be the device address on the bus? I understand this one, my EEPROM has a 3-bit addressing option, which enables me to use 8 chips. This means the maximum address is 0b111. However this should not be on the SDA pin, since its a parallel 3 pins for addressing?
Now what for is the second "i2c_write()" this makes no sense! If the first one is the address, the second one should be the data sent, but its with the same commands, and there is no need to make it i2c_command in the brackets, because it looks like as if this is a parameter from a built-in function, but I see you declared it as a variable. Why "66" exactly?
When I use this code, I have the "sent_byte" variable output on PORT A. What do you think is wrong and can someone explain better please?
Code: |
#include <16F690.h>
#fuses MCLR,NOWDT,NOPROTECT, INTRC_IO
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#use i2c(master, sda=PIN_B4, scl=PIN_B6, FORCE_HW, fast=100000) /* Master mode, SDA pin = RB4, SCL pin = RB6, force hardware i2c functions */
//#use i2c(master,sda=PIN_C4, scl=PIN_C3)
#define Sent_byte 0x01 /* This is the byte that we send to the EEPROM (24AA128) */
void main(void)
{
unsigned int8 read_byte; /* The byte read from the EEPROM (24AA128) */
/*****Initialization********/
/******Analog inputs block******/
/* By default, on power-on, reset, these pins are enabled, if we want to use them as digital, we need to disable them in the initialization section
to spare memory and time in initializing them in the "while(1)" cycle */
setup_comparator (NC_NC_NC_NC); /* Disable analog comparators, pins are available as digital */
setup_vref (FALSE); /* Disable the programmable voltage reference, pin is available as digital */
setup_adc (NO_ANALOGS); /* Disable the ADC module, AN pins are available as digital */
/******Main loop********/
while (1)
{
/*****I2C interface block********/
delay_ms (1000); /* We delay 1sec, to see the result on the output pins of PORTA where we send the read byte from the EEPROM (24AA128) */
printf ("Start i2c Master logger.\r\n");
i2c_start();
i2c_write(Sent_byte); /* We send the "Sent_byte" to the EEPROM (24AA128) */
read_byte = i2c_read(0); /* We read the address from the EEPROM into "read_byte", the "0" is for "Not acknowledge" (??? no acknowledge signal) */
output_a (read_byte); /* We output the "read_byte" on PORTA, to test the result of our program */
delay_ms (1000); /* We delay 1sec, to see the result of the output pins of PORTA, where we send the "read_byte" from the EEPROM (24AA128) */
i2c_write (Sent_byte + 1); /* We send "Sent_byte + 1" to the EEPROM (24AA128) */
read_byte = i2c_read (1); /* We read the address from the EEPROM into "read_byte", the "1" is for to have an "acknowledge" (??? acknowledge signal) */
output_a (read_byte); /* We output the "read_byte" on PORTA, to test the result of our program */
i2c_stop (); /* This is the end of the i2c functions by outputting an "End condition" to the EEPROM 24AA128 */
delay_ms (20); /* ??? 20ms settling time for the i2c functions */
printf ("Ending i2c Master Logger.\r\n");
}
}
|
Can someone tell me how do we set the address of the device to be used? I have EEPROM 24AA128 chips.
Can someone tell me how is the addressing for the memory inside 1 EEPROM chip done? Maybe with "i2c_write(Address)"?
Can someone tell me how is the addressing for the memory inside 1 EEPROM chip done, when reading? I know "C" has automatic addressing for the internal memory, but I don't know how it works for the external EEPROM.
What is the point of mapping registers, when the whole idea of the PIC C compiler is to use built-in functions, which is safer and more maintainable?
I also want to know how to use the "i2c_state()" function to read the state of the bus? And to which pins to connect the bus? This is to indicate if there is transfer from any of the 8 EEPROM chips to the MCU at the moment, I guess?
Also how to display text on the display?
Any good tutorial with steps on the topic of I2C, SPI, RS232, RS485, CAN,USB would be appreciated!
[img]
https://www.dropbox.com/s/q3b26zwy8auzytw/16F690-EEPROM%2824AA128%29.bmp?dl=0
[/img]
Thanks for the help! _________________ Yo! I love learning and technology! I just do not have experience so do not be angry if I ask a stupid question about a detail! From so much to remember sometimes I forget the details in order to remember the big problems! |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Mar 24, 2017 5:28 pm |
|
|
First, tell us where you got this code ? I don't see any #include line
for a CCS driver file.
The data sheet for the 24AA128 shows the following sequence for a
random write operation (on page 9):
http://ww1.microchip.com/downloads/en/DeviceDoc/21191s.pdf
Quote: |
FIGURE 6-1: BYTE WRITE
Start bit
Control Byte
Address: High Byte
Address: Low Byte
Data Byte
Stop bit
|
|
|
|
Arakel
Joined: 06 Aug 2016 Posts: 107 Location: Moscow
|
|
Posted: Fri Mar 24, 2017 6:15 pm |
|
|
I made the code by myself based on what I found in the forum and google. _________________ Yo! I love learning and technology! I just do not have experience so do not be angry if I ask a stupid question about a detail! From so much to remember sometimes I forget the details in order to remember the big problems! |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9243 Location: Greensville,Ontario
|
|
Posted: Fri Mar 24, 2017 6:50 pm |
|
|
The first place to see how to use the device is it's datasheet. Good news is it's 5 volt compatible so it will directly interface with the PIC. Since is follows the I2C protocol, hopefully you've read that you need pullup resistors on the bus.Something like 2K2 might do? Check the datasheet...it will be there...
I suggest downloading PCM P's 'I2C scanner' program and running it. It will confirm IF the PIC can see the EEPROM.
Once that's 'up and running' then see if one of the CCS drivers 'might' be applicable to that EEPROM. One may be close and only need minor changes. Remember do NOT change the CCS driver, make a copy, and make changes to YOUR driver....
As for the various interfacs, best place to start is the datasheets, then application notes, then code examples.In order of easy to hard...my list would be..
RS-232, RS-485, SPI,I2C,USB, CAN.
The first two have 'open protocol' so the user can choose how to design a system...2nd pair have rigid design specs and are short distance devices, last 2 are extremely complicated. The USB 'primer' is a 600 page book, not a quick read. CAN is overly complicated yet easy to hang...
Jay |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Mar 24, 2017 8:03 pm |
|
|
You can write the write_eeprom() function by following what the
24AA128 data sheet tells you. Just translate the operations into
CCS C code as shown below. The operations listed in the data sheet
are in the comments. It translates line for line. Doing this is an
important part of writing a device driver. You must learn this skill.
Code: | void write_eeprom(int8 addr, int8 data)
{
i2c_start(); // Start bit
i2c_write(0xA0); // Control Byte
i2c_write(addr >> 8); // Address: High Byte
i2c_write(addr); // Address: Low Byte
i2c_write(data); // Data Byte
i2c_stop(); // Stop bit
delay_ms(5); // Write cycle time from the data sheet, page 4
}
|
The write cycle time may be shorter than 5 ms. There is an
alternative way to check for "eeprom write cycle done".
It's called "ack polling" and is described in the 24AA128 data sheet.
This method is used by CCS in their eeprom drivers. See below:
Code: |
void write_eeprom(int8 addr, int8 data)
{
int8 status;
i2c_start(); // Start bit
i2c_write(0xA0); // Control Byte
i2c_write(addr >> 8); // Address: High Byte
i2c_write(addr); // Address: Low Byte
i2c_write(data); // Data Byte
i2c_stop(); // Stop bit
// Do "ack polling" to detect end of write cycle.
// See page 9 of the 24AA128 data sheet.
i2c_start();
status=i2c_write(0xa0);
while(status==1)
{
i2c_start();
status=i2c_write(0xa0);
}
i2c_stop();
} |
|
|
|
Arakel
Joined: 06 Aug 2016 Posts: 107 Location: Moscow
|
|
Posted: Fri Mar 24, 2017 9:58 pm |
|
|
By device driver you mean the high to low, low to high transition on SDA, while SCL is high? Probably configuring also all 5-6 registers that control the i2c functions, that i found in the 16f690 datasheet? I was hoping to avoid having to configure all registers, because of the CCS built in functions?
I did not know I need a driver. I will check the 166f690 datasheet.
I already put 1.8k resistors, because the pins are open drain for 16f690 and for the EEPROM. _________________ Yo! I love learning and technology! I just do not have experience so do not be angry if I ask a stupid question about a detail! From so much to remember sometimes I forget the details in order to remember the big problems! |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Mar 24, 2017 10:10 pm |
|
|
By "device driver", I mean a software program that you write, or is
supplied by CCS in the \PICC\drivers folder. I mean for example,
24256.c, or ds1302.c, or mcp4921.c, etc. There are over 200 driver
files in that directory. Example of driver files in that directory:
Quote: |
05/22/2003 02:25 PM 3,453 tones.c
05/22/2003 02:36 PM 1,489 max517.c
06/23/2003 09:58 AM 6,713 adxl210.c
06/23/2003 01:43 PM 4,022 x10.c
06/23/2003 02:43 PM 6,776 sc28l19x.c
06/23/2003 02:45 PM 19,087 rtl8019.c
06/23/2003 02:50 PM 1,982 pcf8570.c
06/23/2003 03:00 PM 3,772 mcp3208.c
06/23/2003 03:03 PM 7,924 max7300.c
06/23/2003 03:06 PM 3,099 ltc1298.c
06/23/2003 03:28 PM 8,849 lmx2326.c
.
.
.
|
|
|
|
Arakel
Joined: 06 Aug 2016 Posts: 107 Location: Moscow
|
|
Posted: Fri Mar 24, 2017 10:29 pm |
|
|
Ok, I will see what happens, however its not easy reading the 300 page 16F690 datasheet, so it will take time to review all of this.
I also thought of reviewing the datasheet and making the device, because this is the right way, however it will take time for everything. _________________ Yo! I love learning and technology! I just do not have experience so do not be angry if I ask a stupid question about a detail! From so much to remember sometimes I forget the details in order to remember the big problems! |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
|
Arakel
Joined: 06 Aug 2016 Posts: 107 Location: Moscow
|
|
Posted: Sat Mar 25, 2017 1:31 am |
|
|
I know what you meant. But I have to go through the PIC datasheet also and learn to read the document. It has interesting things inside. Which are needed in order to setup everything.
Thanks for the help to everyone, I will go through it when I can. _________________ Yo! I love learning and technology! I just do not have experience so do not be angry if I ask a stupid question about a detail! From so much to remember sometimes I forget the details in order to remember the big problems! |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19538
|
|
Posted: Sat Mar 25, 2017 5:23 am |
|
|
One little thing not mentioned so far, is the device address.
The EEPROM data sheet is vital here. The three address pins don't just set the device address to 000 to 111 (assumption made in the post). Look carefully at Figure 5-1 in the data sheet (assuming the MicroChip sheet), entitled 'control byte format'.
The byte is
0b1010aaar
Where 'aaa' are the three address bits, and 'r' is the bus direction flag (1=read, 0=write).
You need to fundamentally understand I2C transactions. The standard is:
1) Start
2) Send device address (bit 0=0 we are writing)
3) Send register address
4w) Then to write, send data - loop here till all sent or end of page
5w) Stop
4r) For read, send Start again here (bus restart)
5r) Send device address (bit 0=1 we want to read)
6r) Now read data - again loop
7r) Stop
The device actual address is a 7bit value sent as the top 7 bits of the first byte sent after a 'start'. The top four bits of this are defined as 1010 for this chip. The address inputs set the low three bits of this.
Some chips talk about their '7bit address' (in this case 0x50 to 0x57), while others talk about the '8bit control/address byte' (which is this 7bit device address rotated once, with the extra read/write bit added). The PIC works with the 8bit format. So (with A0 to A3 off), the chip is on 0xA0 (for write) 0A1 (for read).
Understanding that there is a 'device address', and a 'register address', both of which have to be sent, is vital. |
|
|
Arakel
Joined: 06 Aug 2016 Posts: 107 Location: Moscow
|
|
Posted: Sat Mar 25, 2017 6:44 am |
|
|
Quote: | Understanding that there is a 'device address', and a 'register address', both of which have to be sent, is vital. |
I understand this. I just wanted to know how come we send the register address with the "i2c_write()" command, when this should be for sending data. This is why it made no sense, the same command for the "register address" and for the data?[/quote] _________________ Yo! I love learning and technology! I just do not have experience so do not be angry if I ask a stupid question about a detail! From so much to remember sometimes I forget the details in order to remember the big problems! |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19538
|
|
Posted: Sat Mar 25, 2017 8:19 am |
|
|
The 'write' just means 'send a byte on the bus'.
Part of the I2C standard is that the byte sent _immediately after a start transaction_, is the device address.
Similarly you can't actually just 'read'. If you sent 'start', and then started reading, the bus would be operating the wrong way. The bottom bit of the byte sent after the 'start' determines the bus direction. The bus always starts set for the master to write, until this bit is set to '1' to reverse the bus. |
|
|
Arakel
Joined: 06 Aug 2016 Posts: 107 Location: Moscow
|
|
Posted: Sat Mar 25, 2017 8:49 am |
|
|
Ttelmah wrote: | The 'write' just means 'send a byte on the bus'.
Part of the I2C standard is that the byte sent _immediately after a start transaction_, is the device address.
Similarly you can't actually just 'read'. If you sent 'start', and then started reading, the bus would be operating the wrong way. The bottom bit of the byte sent after the 'start' determines the bus direction. The bus always starts set for the master to write, until this bit is set to '1' to reverse the bus. |
Aha! This is what I needed, now it makes sense. Thank you!
This is how far I got with RS232:
Code: |
#include <16F690.h>
/****CONFIGURATION******/
#fuses MCLR,NOWDT,NOPROTECT, NOBROWNOUT, XT /* Ext. reset, no watchdog, no code protect, no brownout reset,
ext. oscilator */
/****RS232 CONFIGURATION****/
#use delay(clock=4M) /* We specify the clock frequency to use the "delay_()" function, */
#use rs232(baud=9600, parity=N, xmit=PIN_C6, rcv=PIN_C7, bits=8) /* RS232 parameters, baud rate = 9600, no parity bit, transmit pin = RC6, receive pin = RC7,
8 bits per transmitted data */
void main(void)
{
/*****Initialization********/
/******Analog inputs block******/
/* By default, on power-on, reset, these pins are enabled, if we want to use them as digital, we need to disable them in the initialization section
to spare memory and time in initializing them in the "while(1)" cycle */
setup_comparator (NC_NC_NC_NC); /* Disable analog comparators, pins are available as digital */
setup_vref (FALSE); /* Disable the programmable voltage reference, pin is available as digital */
setup_adc (NO_ANALOGS); /* Disable the ADC module, AN pins are available as digital */
/******Main loop********/
while (1)
{
/* To transmit data */
int value = 1;
putc ('A'); /* Transmit a character via RS232 */
puts ("Test-string"); /* Transmit a string via RS232 */
printf ("Transmit a value: %d", value); /* Send formatted string via RS232 */
/* To receive data */
//char ch;
//char string[32];
//ch = getc (); /* Receive a single character via RS232 */
//gets (string); /* Receive a string via RS232, reads characters into the string, until
/*"RETURN" character (13) is encountered */
}
}
|
For some reason, the MPLAB simulator only gives me 0x01 and when I move through the "putc(), puts(), putf()" commands the result stays the same and it does not changes for pin RC6.
[img]
https://www.dropbox.com/s/wxlnmnnaj3r0hk7/RS232-16F690.jpgdl=0
[/img] _________________ Yo! I love learning and technology! I just do not have experience so do not be angry if I ask a stupid question about a detail! From so much to remember sometimes I forget the details in order to remember the big problems! |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9243 Location: Greensville,Ontario
|
|
Posted: Sat Mar 25, 2017 9:41 am |
|
|
One hardware problem I see in your schematic is your MAX232. It needs 4 caps for the charge pump to properly work. Now the old (original) 'MAX232' used 10mfd caps, newer ones smaller value, but still 4 caps. Just Google image 'max232', you'll see what I mean.
Since I never use a simulator, I can't comment on the results but you need to add 'errors' to the #use RS232( ...options....) so the hardware UART won't lockup, freeze when more than 2 characters come from the PC.
Jay |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|