• Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

PIC18F25K42 a work in progress....

Nigel Goodwin

Super Moderator
Most Helpful Member
point 2 Do Rigol really charge 180 quid to licence I2c trigger and decode, My 30 hours nearly up :( ....
No idea, my Rigol is the cheaper DS1052E - no logic facilities.

I do have a very cheap USB logic analyser though, which I'm going to have to dig out and figure out how to use, as I'm still having TFT 'problems'. It's rather strange, I have a couple of ST7735 based TFT's, one is 128x128 (and is shown working from a 24F in the video I posted), the other is 128x160. The setup's for the two displays are slightly different, but if I setup an Arduino Mini Pro for either, I can plug either display in and I get 'some sort' of display, it might be the wrong size or off centred, but it works. With the PIC version only the 128x128 display works, even if I do the 128x160 setup (but obviously wrong size wrong colours etc.) - all I ever get on the 128x160 display on the PIC is a blank white screen.

So I'm a bit bemused, I've even gone to a lot of trouble to try and make the graphics and setup routines as identical as possible - I'm hoping that comparing PIC to Arduino with the analyser might show me the problem?.
 

granddad

Active Member
I have decided not to use the 2x16 blue display, and use a I2C Back_pack slave ( My home brew PIC16F1827 ) , can take most character LCD's, so having to modify old master code from PIC24 progs. So my next post on K42 may be a while ...

I noticed Microchip told me how bad my code was :eek: and suggest I send them some of my pension , to make it run better...
Shame they don't do a "hobbiest" or "Mature student" MPLABX, XC8 version .... :joyful:

omnscient.jpg
I had to check a dictionary for Omniscient ....
 

Nigel Goodwin

Super Moderator
Most Helpful Member
I noticed Microchip told me how bad my code was :eek: and suggest I send them some of my pension , to make it run better...
Actually they told you how bad THEIR code was :D

If you actually google about it, in free mode their compilers deliberately add load's of totally spurious code in order to make the code run slowly, and take up much more space than actually required. A simple loop checking an I/O pin runs so slowly as to make it impossible to read IR remote signals as my assembler tutorials do. But even at that, my XC16 TFT graphics demo on a 24F runs considerably faster than the Arduino version (which is a much lower spec processor).

The MPLABX IDE also runs very slowly, it takes forever to compile XC16 programs, although XC8 ones are a little faster.

I was having speed problems with the Arduino IDE, which I cured by adding various directories to be skipped by my anti-virus, and that helped massively - it compiles quite quickly now.
 

granddad

Active Member
Hi Nigel, I don't recall any compile speed problems with XC16 , but my stuff was not that big ... ,What PIC24 are you using... as I said X seems to run better on linux.mint , screens not a good as windows , perhaps i need a different GUI scheme. any way to take out the MC filler ?
 

Mike - K8LH

Well-Known Member
Grandad, do you know where the configuration word descriptions are? I usually find them in the PIC18F26K42.INC file but they're not there.
 
Last edited:

granddad

Active Member
Hi Mike , You thinking name problems, I usually use the MPLABX memory view , configuration bits , and check / use the drop down boxes , at first run send to output to copy and paste, any help ?
 

Evan VENN

Member
Just spent a few days creating a 12c state engine 18f25k42 (would suit all K42 microcontrollers).

The library provides an ISR to implement of am state I2C hardware slave for these microcontrollers.

This is a Great Cow BASIC implementation of Microchip Application Note AN734 and TB3159 but this is easily, very easily, portable... now I have got it working.

The library and the demonstration responds to a write and reads of bytes to I2C address (the four K42 addresses are supported).

According to AN734, there are 5 possible I2C states, however there is an additional state that is required when AN734 is implemented in anger.

During defined ISR, each 'of these states are detected. The ISR provides a standard skeleton to implement an I2C hardware slaves, while client code must implement several callbacks the ISR is expecting to call while processing states.

Callbacks:
HI2C_Process_In_Message ( in HI2CMESSAGESIZE as byte ) called when slave has recieved a complete I2C write packet

HI2C_Process_Out_Message called when slave is requested to respond to a masters request, the slave needs to send an I2C packet.

In my test code I have a Pot attached and 4 LEDS. The Master will request the value of the Pot and then, the Master will set 3 LEDs to the proportional value of the Pot - and, the Master will set the LEDS to the same value - these LEDs are attached the Master microcontroller.

The test code supports two transactions but this can be easily expanded to support 100s of transaction types.


Transaction #1. Master send I2C packet to address, address, value. as follows to set the LEDs:
0x70, 0x23, 0x00 - turn off all the LEDS
0x70, 0x23, 0x01 - turn on one LED
0x70, 0x23, 0x02 - turn on one LED
0x70, 0x23, 0x03 - turn on two LEDs
0x70, 0x23, 0x04..0xff - turn on LEDs

Transaction #2. Master wants to read the value of the ADC
0x70, 0x81, 0x04, 0x71, 0xNN. Where 0x81 will instruct this slave to read the ADC, where 0x04 equates to ADC4 and then the READ operation will return the single byte value of the Slave ADC to the Master. Any other ADC port request will be returned as 0x00.

To add your own slave commands - simply expand these the example methods.

Findings

AN734 is a very useful architecture of how to create a state engine.
TB3159 is useful but pointless. TB3159 contains three serious errors but at least you can get the microntroller to respond to I2C discovery.
The Great Cow BASIC library, which is based upon the 'Legacy I2C module', shows a reference solution that uses AN734 and completes the approach provided in TB3159.

See https://sourceforge.net/p/gcbasic/discussion/629990/thread/310f10c6/?limit=250#216d for more details.

Thank you.

This thread helped me adapt the existing 'Legacy I2C module' library to support K42 I2C module. With this thread I would have been unable to complete.
 

Attachments

Grasshopper1983

New Member
dear granddad. im trying to initialize my lcd screen on a pic18f45k42 with your code and have i2c now working.

but when i send my lcd bytes to initialize my screen it don't work and hangs.
can you share your lcd code so i can compare it to my code?

im hanging in my code for days now and i want to go futher.

thank you! you helpt me alot already and im learning alot!
 
Last edited:

granddad

Active Member
Hello Grasshopper, my venture into the K42 series project is back in a box somewhere . not sure how far i got with the LCD , as I swapped devices ..
can you share your lcd code so i can compare it to my code?
I'm guessing you want to compare the LCD init string ?... .. I need to go search files.. ... as I have swapped PC as well...
 

Grasshopper1983

New Member
thx for fast reply if it to much work you dont have to search for me.

but yes i was intresting in the "init" part and how you send it to the lcd.

im toggle the eneble bit on the lcd and that works (so i2c works) but i cant get through the lcd init part...
when i try to send more commands the program hangs and i dont know why.
 
Last edited:

granddad

Active Member
I Eventually found the file containing the LCD init .. Bear in mind it is for the Midas I2C display

C:
char LCD_init_data[]={0x00,0x39,0x14,0x7A,0x50,0x6C,0x0C,0x01}; // LCD Init string

void LCD_init()

{

  unsigned int x;

  I2C1ADB1 = 0x7C;   // load addr  7c

  I2C1CNT=0x08;     // load I2C1CNT with number of INIT bytes

  for(x=0;x<8;x++){

  I2C1TXB = LCD_init_data[x];

   while(!I2C1STAT1bits.TXBE); // wait for buffer empty

   }

  while(!I2C1PIRbits.PCIF); // WAIT FOR STOP.

  //serial_print(serial_mess3,1);

  __delay_ms(100);

}
Midas Displays MCCOG21605C6W-BNMLWI COG 2x16 STN White on Blue I2C 61x15.1mm
Vdd can be 3.3 v or 5v
 
Last edited:

Grasshopper1983

New Member
thank you granddad it works now.

C:
void LCD_Init(unsigned int slave_Adress)
{                   //Initialize lcd
                    //set 8bit to 4bit
    int data1[32] = {0x3C, 0x38, 0x3C, 0x38, 0x3C, 0x38, 0x2C, 0x28,
                    
                    //send in 4bits
                    //4-bit mode initialization complete. Now configuring the function set
                    0x2C,0x28,
                    0x8C,0x88,
                    //Next turn display off
                    0x0C, 0x08,
                    0x8C, 0x88,
                    //Display clear, cursor home
                    0x0C, 0x08,
                    0x1C, 0x18,
                    //Set cursor direction
                    0x0C, 0x08,
                    0x6C, 0x68,
                    //Turn on the display. Set cursor and blink here
                    0x0C, 0x08,
                    0xCC, 0xC8,
            
                    //send letter "H"
                    0x4D, 0x49,
                    0x8D, 0x89
                    };
    // Write operation (W/R bit = 0)
    I2C1ADB1 = (slave_Adress<<1)|0;
    int totalByteLength = 32;
    I2C1CNT = totalByteLength;
    I2C1CON0bits.S=1; //Start
    for(int i = 0; i < totalByteLength; i++){   
        __delay_ms(15);
    // Write to TXB starts communication   
        I2C1TXB = data1[i];   
            
        
        //Wait until TXB is empty   
        while(!I2C1STAT1bits.TXBE); 
        
        
    }
    
    while(!I2C1PIRbits.PCIF); // WAIT FOR STOP.
    __delay_ms(100);
    
}


CHEERS!
 

granddad

Active Member
Your welcome... different LCD same method I presume ... I don't profess to be a programmer . far from it . but i just keep 'typing' till i get a result , the K42 is supposed to be more efficient with I2C , no waiting for the slave ACKSTAT.. but I moved on after the RTC chip to some dsPIC33 ... lots of peripherals, and memory and 70MIPS ..
 

Roze

New Member
Hi,
First of all, thanks for a very informative and helpful post.

After several evenings of butting my head against this new way of handling i2c I've now come to the state that I'd like to Shamefully come back here and request some help in converting this attached code into the F24K42 (similar enough to the F25K42). I've been digging in datasheets for well over 16 hours now and I can't say I'm getting any closer to figuring out this new code.

My old code was admittedly initially handed to me by a teacher at the university where I studied. I've modified it quite a bit since,, with bits of code from here and there and quite a bit of my own.

But now I've come to a brick wall in my conversion attempts cause its just so different, everything is differently named and split up in several sub-bits doing different things.

Since you people in this thread seems to have quite a bit of experience with both the new and the old ways, I'd be Very happy to get some help in this conversion process.

I've inlined most, if not all, of my defines to make it easier to follow. It should be a pretty rudimentary I2C code with not much in terms of safety, but it works for me.

//Kind regards, Roze.
 

Attachments

granddad

Active Member
Hi Roze .. I have not done any slave code for K42, and My C is 'amateur' . I did a slave I2C for PIC18F14k22 but steered clear of using an interrupt. so cannot compare.. perhaps explain what is the problem with your code ?.. are you using actual hardware ? ..what is the master PIC ?

Edit, I was incorrect.. I did implement a ISR for I2C slave.. (14K22) ..it was a back-pack for LCD ... seems rather simple ! I have 8 buffers to simplify decoding
C:
void interrupt DATA_IN(void)
{
    if(PIR1bits.SSPIF){
       while(SSPSTATbits.BF){
       I2C_BUF[B_free][SBW] = SSPBUF;
       SBW++;
      }
       if(SSPSTATbits.P){
       B_has_data++;
       B_free++;
       B_free=B_free & 0x0007; // 0-3 buffer numbers
       if(B_free==0)B_free=1;
       SBW=0;
       }
       PIR1bits.SSPIF=0;
    }
    return;
    
 // process other interrupt sources here, if required
}

void EN_interrupts()
{
   char dummy;
   INTCONbits.PEIE_GIEL=1;
   INTCONbits.GIE_GIEH=1;
   PIE1bits.SSPIE=1;  //  enable i2c interrupt. 
   dummy = SSPBUF;
   PIR1bits.SSPIF=0;
}

void I2C_init()   // mssp driver
{
 SSPSTAT = 0x00;   // Slew rate
 SSPCON1 = 0x26;   // SSPEN = 1, I2C Slave mode ,
 SSPCON2 = 0X00;   //
 SSPADD = 0x44;    // SLAVE ADDRESS   
}
 
Last edited:

EE World Online Articles

Loading

 
Top