AT90CAN128 - I2C - LCD

Go To Last Post
23 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi people,

I am fairly new to programming and have quite a task at hand to semi backward engineer a device with the above chip at its core.

Sofar I have managed to get the SPI to comunicate but now find i need to attach an LCD to the I2C bus. I have to use this bus as nearly all other ports have been used for other functions.

Understanding the I2C is a struggle but have used it with the Arduino quite happly but I am struggling to get my head around the concept on the AT90CAN to drive an LCD. Its the libraries that are fighting me!

I have searched this forum and used google extensivly comming up with next to nothing. Could anyone please give me a general pointer to any how-to's or tutorials that may give me a hand in making progress.

The tools I am using are AS6.1 with an AVR dragon while the dev board for testing is the DVK90CAN1.

I dont normally like to ask but i feel i am banging my head on the wall! learning curve is steep!

Any help would be appreciated.

Regards
Nigel

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
i need to attach an LCD to the I2C bus
Is the LCD I2C compatible?
Quote:
nearly all other ports have been used for other functions.
The I2C bus needs 2 pins, an additional CS for the SPI needs 1 pin, any reason why you can't use the SPI?

If you need to use the I2C (TWI for Atmel) then start with some proven libraries so that the learning curve is a little less steep for that.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks John,

The LCD is a normal 4/8 bit mode but is running with a piggyback I2C board. This works with the Arduino using the liquidcrystal includes.

I could probably use the SPI but it is the main purpose of the device, it thakes input from the SPI and converts it to CAN. there is also a lot of other pins used for digital/analog controls.

Thanks for the pointer..

Regards
Nigel

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think I have bitten off more than I can chew!

it appears I haven't got the SPI slave to work fully.

I will explain more. I have a SPI bus that transmits two groups of 3 bytes for each time I press a button.

I was trying to use an ISR as below:-

ISR (SPI_STC_vect)
{	

	while(!(SPSR & (1<<SPIF))) ;
	buf[bit_counter] = SPDR ;
	bit_counter ++;
	if (bit_counter >= 3) // IF THREE BYTES HAVE BEEN RX RESET COUNTER		
	{			
	bit_counter = 0;
	incomming = true;							
	}	
}e]

this code just hangs at the while.

I have checked the SS line and the master is set as output.

Am I correct that the first time through the while statement should be true and allow the SPDR to be read? then as the SS line is still low it should wait till the next byte comes in then read?

I am really stuck here and would appreciate guidance. I have read the data sheets and am getting nowhere.

Regards
Nigel

Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
this code just hangs at the while.
Tried removing it? SPIF gets cleared automatically by the hardware within the ISR so it may not be set when you try and test it.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes I tried that but it puts the incoming data in the wrong places of the array.

It seems to put the last bit in [0] the first in [1] and 0 in [2].. I have missed something real basic and its killing me..

Nigel

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

once the 1st byte is read and the ISR is triggered how do you detect the next byte is ready to be read?
Nigel

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
It seems to put the last bit in [0]
Then you need to reverse the data order with the DORD?? bit.
Quote:
how do you detect the next byte is ready to be read?

Wait for the next ISR. Remember that NO DATA will come in unless you send a dummy data out.

And why are we talking about SPI when the original title talks about I2C? :-)

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

last question first - I did question this in a separate post but no replies after 2 weeks so re arranged the question on my original I2C post. sorry.

I understood the DORD was a byte order, sort of read from left to right and when changed it was read right to left.

I will look at the dummy data as I haven't explicitly made that happen. thanks for the help.

Nigel

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What devices do you have on the SPI bus?

Your Logic Analyser showed activity on the MISO line when SS was high !
Most SPI devices have an active-low CS pin.
If you have a non-standard device, tell your Logic Analyser that CS is active-high. Then it will decode the traffic accordingly.

SPI is pretty easy to use from a Master's point of view. Select CS, send N bytes, deselect CS.

Most SPI devices can work far faster than the AVR. So you can run at high speed and simply poll. This is more efficient than using interrupts.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

last question first - I did question this in a separate post but no replies after 2 weeks so re arranged the question on my original I2C post. sorry.


Interesting, as all of your posts on these forums to this date are in this thread.

Quote:

Most SPI devices can work far faster than the AVR. So you can run at high speed and simply poll. This is more efficient than using interrupts.

I agree that for a typical SPI transaction of a few bytes to just do it "in place" and not fuss with SPI interrupt.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

thanks guys,
I did delete the other thread as no replies were seen after 2 weeks.

The picture above was captured from the automotive SPI bus and it seems to show two bursts of 3 bytes, and I agree there appears to be activity with SS high. That activity is always there and SS is always high and it is always the same three bytes 61,255,255
I don't know what chips are used on the automotive system but I am using an Arduino uno as the master SPI and an AT90CAN128 as slave.

I am backwards engineering the AT90CAN part of the system so am stuck with SPI as the control data.

I really appreciate your help guys, an will now investigate the polling method and ditch the ISR for the time being.

Nigel

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm doing some automotive can bus capturing and reverse engineering. I have a kvaser leaf can reader and I use canking to capture stuff. Might I inquire about what the spi data is squirting out of? Just curious.

Imagecraft compiler user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
I understood the DORD was a byte order, sort of read from left to right
Correct, but you wrote about BITS being in the wrong order above or maybe I didn't understand what you said. :-)
Quote:
It seems to put the last bit in [0] the first in [1] and 0 in [2]..
So are you saying that the bytes in the array are put in the wrong location?

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

yes sorry was a long day! I meant bytes, I am sure it has something to do with the SS line low through all 3 bytes.

I am awaiting delivery of a storage scope/analyser so I can see what's happening. all my test equipment is in New York and I only have a small single trace scope.

I will try some more things and come back here when I have more definite information.

one route I did try today was another Arduino as a slave. this also didn't work and had the same poor transfer of data. this did work before so suspect the master is having problems.

Thanks for the help thus far.

Nigel

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ok I now have even less hair! I think I had a small problem with the dev boards I made! I had an earth missing or it was using the AGnd.

I now have some data transferring over the SPI but only every other 3 byte group transfer. the first group never progresses but the second group does.

when I pause the code (AS6.1) it appears to be hung at the line in the ISR

while(!(SPSR & (1<<SPIF))) ;

The data is coming from an Arduino Uno with an adafruit lcd/button shield. The SPI waveforms looks ok on my cheap one channel scope. I can post the Arduino sketch if required but today will only post the AVR slave code.


/*
 * Bike_MP3.cpp
 *
 * Created: 7/30/2013 8:01:43 AM
 *  Author: nigel
 *
 *
 *
 *
 */ 
#ifndef F_CPU
#define F_CPU 16000000UL // or whatever may be your frequency
#endif

#define	__AVR_AT90CAN128__	1
#define OSCSPEED	16000000		/* in Hz */


#include 
#include 
#include 
#include 

#define DDR_SPI DDRB
#define DD_MISO DDB3
#define DD_MOSI DDB2
#define DD_SCK DDB1
#define DD_SS DDB0



int i ;
int k ;
volatile char buf[3];
volatile int bit_counter;
volatile int incomming = 0;


void SPI_SlaveInit(void)
{
	DDRB &= ~((1<<2)|(1<<3)|(1<<5));   // SCK, MOSI and SS as input
	DDRB |= (1<<4);                    // MISO as output
	SPCR &= ~(1<<MSTR);                // Set as slave
	SPCR |= (1<<SPE)|(1<<SPIE);//Enable SPI, SPI int vector
}





void PORT_Init()
{

	PORTA = 0b00000000;
	DDRA  = 0b11111111;    // PTT - 2x VOL - 2x SS for vol

	PORTB = 0b00000000;
	DDRB  = 0b00000000;	   //  SPI - 

	PORTC = 0b00000000;
	DDRC  = 0b11111111;	   //  Audio Mux

	PORTD = 0b00000000;
	DDRD  = 0b11111111;	   // CAN BUS

	PORTE = 0b00010000;		//Turn Led off (Bit4 = 1)   4x IO for 2nd radio and some interuups for muts etc
	DDRE  = 0b00010000;		//Led set as output (Bit4 = 1),  

	PORTF = 0b00000000;
	DDRF = 0b00000000;	    //  JTAG and audio tones
}


ISR(SPI_STC_vect)
{
	PORTD ^= 1 << PIND0;			// debug marker port pin toggle
	buf[bit_counter] = SPDR ;
	bit_counter = bit_counter + 1;
	PORTD ^= 1 << PIND0;			// debug marker port pin toggle
}



int main()
{
	incomming = 0;
	bit_counter = 0;

	PORT_Init();
	SPI_SlaveInit();

	sei();
	while (1)
	{
		if (bit_counter > 2 ) // IF THREE BYTES HAVE BEEN RX RESET COUNTER
		{
			
			{
				bit_counter = 0;
				incomming = 1;
			}
		
			
		}
	}
}

 

edited to show only SPI code

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok now I edited the code above to what I am using, I also removed some procedures that were not needed here.

I have finally got a Logic analyzer to watch and document my predicament.

The SPI 3 byte TX is all ok from the arduino but it appears the AT90can is not generating an SPI IRQ after RX of each BYTE. I have looked but cant see anything obvious. One thing I looked at and still trawling the net about is the Fuse setting of the 16 Mhz external Xtal. There appears to be no setting AS6 seems only to go to 8 Mhz -- I still have lots to read about.

the ISR is set to toggle a port pin going in and out of the IRQ.

Any suggestions why the chip is not responding correctly?

Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You normally set SS low for the whole 3-byte SPI sequence. You seem to have about 125kHz SCK clock. So handling an SPI interrupt every 200us is pretty trivial for an 8MHz AVR.

No, I can't see why you don't get the 2nd IRQ.

Which Logic Analyser and what software are you using ?

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks David,

The analyser is the ChronoVu and the software is what came with it!.. works a treat and is not very expensive.

http://www.chronovu.com/

The MCU im using is the AT90CAN128 and has an external 16Mhz Xtal. are there any settings I should use? I have just tried the check for SS low and wait till its read the byte in but it still fails to read the byte. is it possible the mosi/miso lines need pullups or something?

Nigel

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The LA-8 looks very interesting. I use a Salae which I am very happy with. The LA-8 looks very practical i.e. speed and number of samples. It is a similar price. The probes look poorer quality.

Most of the 'other' fast LAs can manage the speed but are limited for samples.

Your Slave looks fine to me. If you post your Master sketch, I might compile both programs and try it myself. I can't see why you don't get an IRQ for each byte.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

oh missed "sketch"!


// added code by Nigel Fenton - 3:21pm 4/20/2013
#include 
#include 
#include 
#include 
#include 


Adafruit_RGBLCDShield lcd = Adafruit_RGBLCDShield();
int volume;
int squelch;
int channel;
int addr = 0;
int buffer_size = 3;
byte stored_value;
int message_command[] = {61, 255, 255};
int message_VOL[]  = {189,237,volume};
int message_SQLU[] = {189,203,squelch};
int message_SQLD[] = {189,111,squelch};
int message_CHA[]  = {189,238,channel};
byte c;
#define SS 10


#define WHITE 0x7
#define BLACK 0x0
  uint8_t i=0;
  uint8_t oldButtons;



void setup (void)
{
 
  Serial.begin(115200);
  lcd.begin(16, 2);
  lcd.setBacklight(WHITE);
   Wire.begin(); // join i2c bus (address optional for master)
   pinMode(SS, OUTPUT);
   

  SPI.begin (); 
  SPI.setClockDivider(SPI_CLOCK_DIV128); // Slow down the master a bit  
  volume = EEPROM.read(0);
  squelch = EEPROM.read(1);
  channel = EEPROM.read(2); 
}  // end of setup

void i2c_send_out(char ca)
{
   Wire.beginTransmission(4); // transmit to device #4
   Wire.write(ca);              // sends one byte  
   Wire.endTransmission();    // stop transmitting
}

void updateLCD(){
  lcd.clear();
  lcd.setCursor(0,1);
  lcd.print("VL ");
  lcd.print(volume);
  lcd.print(" SQ ");
  lcd.print(squelch);
  lcd.print(" CH ");
  lcd.print(channel);
  lcd.setCursor(0,0);
  lcd.print("NIGEL SPI SENDER");
}

void loop (void){
 
 byte c; 
 //updateLCD();  
   digitalWrite(SS, HIGH);  // ensure SS stays high for now
 while (1){
  uint8_t newButtons = lcd.readButtons();
  uint8_t buttons = newButtons & ~oldButtons;
  oldButtons = newButtons;
  
  if (buttons) {
    lcd.setCursor(0,1);
    if (buttons & BUTTON_UP) {
      if (volume < 20){
      volume = volume + 1;
      EEPROM.write(0, volume);
      message_VOL[2] = volume ;
      //updateLCD();
      for (int p =0; p  0){
      volume = volume - 1;
      EEPROM.write(0, volume);
      message_VOL[2] = volume ;
    //  updateLCD();
      for (int p =0; p  0) {
       squelch = squelch - 1;
       EEPROM.write(1, squelch);
       message_SQLD[2] = squelch ;
       //updateLCD();
      for (int p =0; p 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am rapidly losing faith in the AS6 debugging. It appears changing where you set debug points it changes the way the AVR runs. I think I need to move debugging to the serial port.

N

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well I think I found my problem. I was not code but hardware.

It turned out to be the regulated 5v psu. It was feeding the Olimex board to a further 5v regulator. That should work fine but it caused a further 1 to .6 volt drop. Now I feed the 5v directly to the post regulated supply I am not missing any IRQ's Hoorah!!

Thanks for the help in the background David et all.

Regards Nigel.... now back to the I2C....