Hello.
I have a problem using hardware I2C with a PIC18F47K40.
I use I2C1.
Basically the program crashes when I go to write the address.
As a test I adapted a sample program and added an LCD display to it for convenience.
The serial and the display work perfectly. The problem is on I2C1.
This is the test program:
#OptionExplicit' -' -
#Chip18F47K40, 64
#ConfigOSC=INT', MCLR_OFF' -' Configurazione dei pins per la seriale e il bus I2C
#StartUpInitPPS, 85
#DefinePPSTOOLPART18f47k40
#DefineLCD_IO4
#DefineLCD_NO_RW
#DefineLCD_SPEEDfast;Change As necessary
#DefineLCD_RSPORTD.6
#DefineLCD_ENABLEPORTD.7
#DefineLCD_ENABLE2PORTE.2
#DefineLCD_DB4PORTD.2
#DefineLCD_DB5PORTD.3
#DefineLCD_DB6PORTD.4
#DefineLCD_DB7PORTD.5' Define I2C settings
#DefineHI2C_BAUD_RATE100
#DefineHI2C_DATAPORTC.4
#DefineHI2C_CLOCKPORTC.3' Initialise I2C - note for the I2C module the ports need to be set to Output.DirHI2C_DATAOutDirHI2C_CLOCKOut' Setup Serial port
#DefineUSART_BAUD_RATE9600
#DefineUSART_TX_BLOCKINGDimDeviceIDAsByteDimDISPLAYNEWLINEAsByteClsPrint"Start test I2C"DoHSerPrintCrLfHSerPrint"Hardware I2C "HSerPrintCrLf2' Now assumes Serial Terminal is operationalHSerPrintCrLfHSerPrint""' Create a horizontal row of numbersForDeviceID=0to15HSerPrinthex(DeviceID)HSerPrint""Next' Create a vertical column of numbersForDeviceID=0to255Locate3,1PrintDeviceIDDISPLAYNEWLINE=DeviceID%16IfDISPLAYNEWLINE=0ThenHSerPrintCrLfHSerPrinthex(DeviceID)IfDISPLAYNEWLINE>0ThenHSerPrint""EndIfEndIfHSerPrint""' Do an initial StartHI2CStartIfHI2CWaitMSSPTimeout<>TRUEThen' Send to address to deviceHI2CSend(DeviceID)' Did device fail to respond?IfHI2CAckPollState=FALSEThenHI2CSend(0)HSerPrinthex(DeviceID)ElseHSerPrint"--"EndIf' Do a stop.HI2CStopElseHSerPrint"! "EndIfNextHSerPrintCrLf2HSerPrint"End of Search"HSerPrintCrLf2Wait5sLoop' -' -SubInitPPSUnLockPPS'Module: EUSART1RC6PPS=0x0009'TX1 > RC6 25RX1PPS=0x0017'RC7 > RX1 26'Module: MSSP1SSP1DATPPS=0x0014'RC4 > SDA1RC4PPS=0x0010'SDA1 > RC4 (bi-directional)RC3PPS=0x000F'SCL1 > RC3SSP1CLKPPS=0x0013'RC3 > SCL1 (bi-directional)LockPPSEndSub
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
So, the error is the direction of the I2C ports. They should be IN.
See demo - C:\GCB@Syn\GreatCowBasic\Demos\vendor_boards\great_cow_basic_demo_board\18f27k40_chiprange_demonstrations\150_show_i2c_devices_to_serial_terminal.gcb
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Nothing to do!
the hardware is connected well, there are pullup resistors, I have inserted a PCF8574 in the bus but I can not write or read in any way.
I tried to use the Mikrobasic compiler as well with the same result.
I doubt that it could be the micro, but it would be the first time ...
For the moment I do not have another to try, when I return to Rome I will do some tests.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I have adapted the code for the PIC18F47K40.
Although there are devices connected to the I2C bus, they are not recognized.
At this point I think it's the faulty micro
' ''' ''******************************************************************' ''' ''' ''' '' PIC: 18F47K40' '' Compiler: GCB' '' IDE: GCB@SYN' ''' '' Date: 29.8.2019' ''' ----- Configuration' Chip Settings.#Chip 18F47K40,32#Option Explicit#Config MCLRE=Off' Generated by PIC PPS Tool for Great Cow Basic' PPS Tool version: 0.0.5.26' PinManager data: v1.76' Generated for 18F47K42'' Template comment at the start of the config file'#StartUp InitPPS, 85#Define PPSToolPart 18F47K40' ODCC3=1 'SetpinAsopendrainOutput' Template comment at the end of the config file#Define USART_BAUD_RATE 9600#Define USART_BLOCKING' #Define sync SYNC_TX1STA;-----DefineHardwaresettingsForhwi2c' Define I2C settings - CHANGE PORTS if required for your specific device.#Define hi2c_BAUD_RATE 400HI2CModeMaster;-----Mainbodyofprogramcommenceshere.' Now assumes Serial Terminal is operationalDimDeviceIDAsByteDimDISPLAYNEWLINEAsByte'-'-HSerPrintCrLfHSerPrint"Hardware I2C "HSerPrintCrLf2'-HSerPrint" "ForDeviceID=0to15HSerPrinthex(deviceID)HSerPrint" "Next'-ForDeviceID=0to255DisplayNewLine=DeviceID%16IfDisplayNewLine=0ThenHSerPrintCrLfHSerPrinthex(DeviceID)HSerPrint": "EndIfHSerPrint" "HI2CStartIfHI2CWaitMSSPTimeout<>TRUEThenHI2CSend(deviceID)IfHI2CAckPollState=FALSEThenHSerPrinthex(deviceID)ElseHSerPrint"--"EndIfHI2CSend(0)EndIfHI2CStopNext'-HSerPrintCrLf2HSerPrint"End of Search"HSerPrintCrLf2Wait1sEnd'-'-'-SubInitPPS'Module: I2C1'Module: MSSP1'Module: EUSART1RC6PPS=0x0009'TX1 > RC6RX1PPS=0x0017'RC7 > RX1'Module: MSSP1SSP1DATPPS=0x0014'RC4 > SDA1RC4PPS=0x0010'SDA1 > RC4 (bi-directional)RC3PPS=0x000F'SCL1 > RC3SSP1CLKPPS=0x0013'RC3 > SCL1 (bi-directional)'Module: I2C1 extra settings' This is a dedicated PIC I2C module' The clock speed is 125kHz by default (not 100kHz/400kHz)' See the HWI2C section of the Help, or refer to the chip specific datasheet, for how to change the clock speed to the desired frequency#Define HI2C_DATA PORTC.4 'Define a constantDirHI2C_DATAOut'Set I2C pin As Output' RC4I2C_TH0=1 'SettheI2ClevelforthepinODCC4=1'Set pin As open drain Output#Define HI2C_CLOCK PORTC.3 'Define a constantDirHI2C_CLOCKin'Set I2C pin As Output' RC3I2C_TH0=1 'SettheI2ClevelforthepinODCC3=1'Set pin As open drain OutputDirPORTC.6in' Make TX1 pin an OutputEndSub
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I assumed you have the original PPS correct but you had SDA and SCL and it should be SDA and SCK.
I may not have the ports correct.
Evan
'Generated by PIC PPS Tool for Great Cow Basic'PPS Tool version: 0.0.6.2'PinManager data: v1.81.0'Generated for 18f47k40''Template comment at the start of the config file'
#startupInitPPS, 85
#definePPSToolPart18f47k40SubInitPPS'Module: MSSP1RC4PPS=0x0010'SDA1 > RC4SSP1DATPPS=0x0014'RC4 > SDA1 (bi-directional)SSP1CLKPPS=0x0013'RC3 > SCK1RC3PPS=0x000F'SCK1 > RC3 (bi-directional)EndSub'Template comment at the end of the config file
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hi Evan.
Thank you so much for the help you gave me, very important.
A question:
The micro has two serial ports. Is it possible to access both simultaneously in order to read data from one and, after processing, send them with the other port ?
Thanks
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
So, you (as I wrote) need two buffers driven by the interrupts. When some arrives it gets sent out. YOU CANNOT use one buffer.
Take the existing Help example code. Adapt all the constants and variables to manage one port. So, rename everything... this is a little example
SubreadUSART_USART1buffer_USART1(next_in_USART1)=HSerReceive(1)temppnt_USART1=next_in_USART1next_in_USART1=(next_in_USART1+1)%BUFFER_SIZEIf(next_in_USART1=next_out_USART1)Then' buffer is full!!next_in_USART1=temppnt_USART1EndIfEndSub
I would convert the existing code using ONE USART (so, it does the loop back as per the Help example) and ONLY when you have the working with all the new constants and variables then expand to USART2. (this is a little piece converted )
SubreadUSART_USART2buffer_USART2(next_in_USART2)=HSerReceive(2)temppnt_USART2=next_in_USART2next_in_USART2=(next_in_USART2+1)%BUFFER_SIZEIf(next_in_USART2=next_out_USART2)Then' buffer is full!!next_in_USART2=temppnt_USART2EndIfEndSub
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
What are you trying to with the serial stuff? You may be able to do this using CLC... essentially, signal in to signal out with zero cpu usage. It all depends on what you are trying to do.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I want to modernize the home automation unit I have in the house by the sea.
The control unit communicates in RF with various peripherals, from the sectoral irrigation system, to the various thermostats located in each room, to lighting control, opening gates, weather stations, etc.
All can be controlled remotely by GSM.
I actually use three serial ports: two hardware and one software. The hardware ports are connected to the GSM modem and the other to the TX that I use to communicate with the peripherals.
I use the software serial port to communicate with a PIC12F1840 that decodes the signals coming from the various remote controls.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
The buffer should work for you, but, if the incoming messages are formatted/structured , or CR/LF terminated then you may be able to use HSerGetString()
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Actually I have to read all values from 0 to 255, so I read and parse each byte.
The protocol is the one developed years ago and which is recognized by all installed devices.
The message with the commands to be executed normally consists of a preamble of three bytes, a command of twelve bytes followed by the CRC.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hello.
I have a problem using hardware I2C with a PIC18F47K40.
I use I2C1.
Basically the program crashes when I go to write the address.
As a test I adapted a sample program and added an LCD display to it for convenience.
The serial and the display work perfectly. The problem is on I2C1.
This is the test program:
What version of the compiler? Compiles ok on ;Program compiled by Great Cow BASIC (0.98.07 2021-06-07 (Windows 64 bit)) for Microchip MPASM
What do you mean by program crashes is the compiler crashing?
This is my version:
Compiler Version: 0.98.<<>> 2021-05-21 (Windows 64 bit) Program Memory: 1044/65536 words (1,59%) RAM: 46/3720 bytes (1,24%) OSC: HFINTOSC_1MHZ, 64Mhz (Internal oscillator) Chip: 18F47K40
The compilation is fine.
Program operation hangs on "HI2CSend"
Upload your HWi2c.h. I will compare to the released version. Then, I can advise.
I did test the library prior to release but by comparing yours and the released file(s) will help.
Ok.
No issue with the file.
So, the error is the direction of the I2C ports. They should be IN.
See demo - C:\GCB@Syn\GreatCowBasic\Demos\vendor_boards\great_cow_basic_demo_board\18f27k40_chiprange_demonstrations\150_show_i2c_devices_to_serial_terminal.gcb
OK. Itest.
Nothing to do!
the hardware is connected well, there are pullup resistors, I have inserted a PCF8574 in the bus but I can not write or read in any way.
I tried to use the Mikrobasic compiler as well with the same result.
I doubt that it could be the micro, but it would be the first time ...
For the moment I do not have another to try, when I return to Rome I will do some tests.
Your code is missing --- check the demo....
I have adapted the code for the PIC18F47K40.
Although there are devices connected to the I2C bus, they are not recognized.
At this point I think it's the faulty micro
You have mixed up the pps from two totally different chips.
Go back to the firsr code you posted and add hi2cmode master.
I cannot test, but, this your code. WIth the bits I mentioned sorted.
I assumed you have the original PPS correct but you had SDA and SCL and it should be SDA and SCK.
I may not have the ports correct.
Evan
I have taken your program first posted
Change the PPS, commented out the LCD debug, added the missing DIR and HI2Cmode and most importantly sorted the PPS.
Works
Hardware I2C - I have a I2C display connected on addresses 0x78 and 0x79
Hi Evan.
Thank you so much for the help you gave me, very important.
A question:
The micro has two serial ports. Is it possible to access both simultaneously in order to read data from one and, after processing, send them with the other port ?
Thanks
Yes.
Use a serial ring buffer one for each serial port, then, send the buffer out on the opposite port. Very simple to implement.
See the help for the one port implementation. You will need to expand the solution to cover two ports but this is easily doable.
I assumed the ports where bi-directional.
USART 1 RX > USART 2 TX
USART 2 RX > USART 1 TX
So, you (as I wrote) need two buffers driven by the interrupts. When some arrives it gets sent out. YOU CANNOT use one buffer.
Take the existing Help example code. Adapt all the constants and variables to manage one port. So, rename everything... this is a little example
I would convert the existing code using ONE USART (so, it does the loop back as per the Help example) and ONLY when you have the working with all the new constants and variables then expand to USART2. (this is a little piece converted )
Thank you.
Now I play with it a little ...
What are you trying to with the serial stuff? You may be able to do this using CLC... essentially, signal in to signal out with zero cpu usage. It all depends on what you are trying to do.
I want to modernize the home automation unit I have in the house by the sea.
The control unit communicates in RF with various peripherals, from the sectoral irrigation system, to the various thermostats located in each room, to lighting control, opening gates, weather stations, etc.
All can be controlled remotely by GSM.
I actually use three serial ports: two hardware and one software. The hardware ports are connected to the GSM modem and the other to the TX that I use to communicate with the peripherals.
I use the software serial port to communicate with a PIC12F1840 that decodes the signals coming from the various remote controls.
The buffer should work for you, but, if the incoming messages are formatted/structured , or CR/LF terminated then you may be able to use HSerGetString()
Actually I have to read all values from 0 to 255, so I read and parse each byte.
The protocol is the one developed years ago and which is recognized by all installed devices.
The message with the commands to be executed normally consists of a preamble of three bytes, a command of twelve bytes followed by the CRC.
Sounds good.