i2c analysis on oscilloscope - embedded

I am using a cortex m3 based mc.
I scoped my communication with a logic analyzer, but I don't really understand what I see. Can you help me?
I am using 10k pull up resistors
I am trying to send the data: 0x55 . I (think) don 't see the data, only an -address
On the following pictures you can see the address, but I think it s not correct or am I mistaking.
There is no sensor wired to the mc yet, I changed the address to analyze.
adress 0x00, data 0x55 : http://imgur.com/OJfe8Dj,7REdHS7,PLz1qTZ
address 0x55, data 0x55: http://imgur.com/OJfe8Dj,7REdHS7,PLz1qTZ#1
address 0xff, data 0x55: http://imgur.com/OJfe8Dj,7REdHS7,PLz1qTZ#2
My code:
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C7);
GPIOPinConfigure(0x00001002);
GPIOPinConfigure(0x00001402);
GPIOPinTypeI2C(GPIO_PORTA_BASE, GPIO_PIN_5);
GPIOPinTypeI2CSCL(GPIO_PORTA_BASE, GPIO_PIN_4);
I2CMasterInitExpClk( I2C7Master_Base, SysCtlClockGet(), false);
I2CMasterSlaveAddrSet(I2C7Master_Base, 0xff, false);
I2CMasterDataPut(I2C7Master_Base, 0x55);
I2CMasterControl(I2C7Master_Base, I2C_MASTER_CMD_SINGLE_SEND);
while(I2CMasterBusy(I2C7Master_Base));
Can somebody give an explanation?

Indeed you better make a wired connection between master and light sensor. Then you need to send a proper address of the sensor which should be acknowledged by slave. You will see ACK-bit in the scope when the slave acknowledges on its address. Next you are going to operate with data according to the datagrams on the sensor - any data byte should be also acknowledged (most likely, or kind of due to datasheet). Start with wired connection because there is no big sense to try I2C bus without load, we can't even see 8-9 clock cycles on the diagram you posted because it is without load connection I think. Hope it helps.

Related

STM32f103 HAL USB - UART bridge

I have a third party device that is UART programmable.
I need to create a USB - UART bridge with a functional password (programming only after entering the correct password)
generated the code using the latest version of STM32CubeMX for Atollic TrueSTUDIO for STM32 9.3.0 ...
I transfer data between USB and UART through a buffer (one for usb-uart, and another one for uart-usb)
when I try to transfer several characters everything is OK, but when I try to transfer a large data packet, problems start due to the fact that the USB speed is much higher than the UART ...
there are two questions:
1.How do I tell USB that I need to stop transferring data and wait until the UART (buffer) is busy
2.How on the side of the microcontroller to get the baud rate set on the PC (set when the terminal is connected to the virtual COM port)
USB provides flow control. That's what you need to implement. A general introduction can be found here:
https://medium.com/#manuel.bl/usb-for-microcontrollers-part-4-handling-large-amounts-of-data-f577565c4c7d
Basically, the setup for the USB-to-UART direction should be:
Indicate that the code is ready to receive a USB packet
Receive a USB packet
Indicate that you are no longer ready to receive a USB packet
Transmit the data via UART
Start over
Step 0: Initial setup
Call USBD_CDC_SetRxBuffer to set the buffer for receiving the USB data. Unless you use several buffers to achieve higher throughput, a single call at the start of the program is sufficient.
Step 1: Ready to receive data
Call USBD_CDC_ReceivePacket. Other than what the name implies, this function indicates that the app is ready to receive data. It immediately returns before the data has actually been received.
Step 2: Receive a USB packet
You don't need to do anything here. It will happen automatically. Once it's complete, CDC_Itf_Receive will be called.
Step 3: Indicate that you are no longer ready to receive a USB packet
Nothing to do here. This happens automatically whenever a packet has been received (and double buffering is not enabled).
Step 4: Transmit the data via UART
I guess you know how to do this. It's up to you whether you want to do it in a blocking fashion or using DMA.
Since a callback is involved, you cannot put this code into the main loop. It might be possible to put all code into CDC_Itf_Receive if blocking UART is used. It would appear in the order 2, 3, 4, 1. Additionally, initialization is needed (0 and 1).
In the UART-to-USB direction, you would need to implement flow control on the UART. The USB flow control is managed by the host. Even though USB is much faster than UART, flow control is relevant as the application on the host can process data as slow as it likes to.
Regarding question 2: I'm not sure I understand it... The microcontroller cannot set the baud rate on the host. Either the host can specify a baud rate (transmitted over USB and applied to UART), or if the UART has a fixed baud rate, you can ignore baud rate (any baud rate set on the host side will work as it does not apply to USB).

Are all zeros valid SPI read/write data?

If yes, how does the hardware know if there's really data or not since the level on the MOSI/MISO line never changes.
I assume that with SPI you mean Serial Peripheral Interface.
According to wikipedia, the data is sent like this:
During each SPI clock cycle, a full duplex data transmission occurs. The master sends a bit on the MOSI line and the slave reads it, while the slave sends a bit on the MISO line and the master reads it. This sequence is maintained even when only one-directional data transfer is intended.
(https://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus#Data_transmission).
Because it works with a clock, sending (only) zeros should work.
Besides that, with something like the Manchester code, the MOSI/MISO line would change. I'm not sure if this can be used with the Serial Peripheral Interface though.

Accurately measuring Time for an event ( relay contact closure) using GPS PPS

I have a relay contact closure event that needs to be timestamped accurately ( 1 msec) with a GPS and the PPS output... I am not sure how to feed the relay contact output to a microcontroller and then synchronize the microcontroller clock to the GPS ...plus how to get the UTC afterall?
Can you please help me.
thanks
If your microcontroller has at least two interrupts based on hardware pins, you could connect the relay to one of the interrupt-generating pins, and the PPS to the other interrupt-generating pin.
You will need to connect the NMEA (or other proprietary protocol of your GPS) to the corresponding port in your microcontroller. Some common buses are UART or SIP.
Then, every time that you get a PPS interrupt, you enable a global flag that can be used in the main loop to reset a counter. This counter will tell you how far apart from the PPS the relay switched (if it happens within that second). If you know the base frequency of your counter, you can convert the counter into fractions of seconds. Note that if both edges of the relay state change have to be detected, you will need an interrupt source capable to interrupt on both edges (or use two interrupts)
Then, if the Relay interrupt goes off, you can get the value of the counter upon interrupt, and save it in storage, send it to host, etc. (Note, it would be best to save the value in RAM, lift a flag of "value present", and leave the sending/storing to the main loop, then turning off the flag).
Finally, when you receive a complete NMEA message (this could be being parsed in your main loop by a state machine for instance), you can send this information to the host or storage along with the counter that you saved to time your relay state change. Note please that the NMEA message will be generated and decoded with a certain delay from the PPS, so you will need to compensate for that.

Making I2C work on PIC18

I'm using PIC18F87J11 as the master and LiPower Shield as the slave, and all I want to do is to be able to read the battery voltage value from the LiPower Shield. I'm using MPLAB C18 libraries for the I2C communication. I'm not able to get correct readings as I think the communication between the two devices is not setup correctly.
I'm looking for interpretations of the waveform signals in order to detect the issue. Also I would like to know if I'm missing something in the code. Any recommendations to improve the code would be helpful.
The LiPower Shield came with a sample code for Arduino but I'm using PIC18 chip from Microchip. The sample code is found here.
Here is the signals I'm getting while trying to read the battery voltage.
Code:
SSP2ADD = 19;
OpenI2C2(MASTER,SLEW_OFF);
StartI2C2();
IdleI2C2();
WriteI2C2(0x36);
IdleI2C2();
data = ReadI2C2(); // Read byte of data
printf ("\r\nAddress 32");
printf (" Byte:");
PrintChar(data);
IdleI2C2();
AckI2C2();
IdleI2C2();
WriteI2C2(0x02);
IdleI2C2();
data = ReadI2C2(); // Read byte of data
printf ("\r\nAddress 02");
printf (" Byte:");
PrintChar(data);
IdleI2C2();
AckI2C2();
StopI2C2(); // Stop condition I2C on bus
Output: Which I think is wrong.
Address 32 Byte:FF
Address 02 Byte:FF
I'm not really sure if I'm writing/reading from the correct address, but that's the address they used in the their sample code. I hope I can get some interpretations on the signals and feedback on the code if possible.
I'm not familiar with the PIC but your code looks nowhere near right. Per the MAX17043DS datasheet, page 12, a memory read must consist of the following:
I2C start condition
Write device I2C write address (0x6C)
Check for ACK from slave
Write 8-bit memory address
Check for ACK from slave
I2C repeated start condition
Write device I2C read address (0x6D)
Read first byte of data
Send ACK
Read second byte of data
Send NACK
I2C Stop condition
What I see in your code is an I2C Start condition followed by a write 0f 0x36. Since this is not the device address the slave recognizes, it sends a NACK (as seen on your logic analyzer traces) and ignores everything else.
This question and answer has a lot of information on I2C on a PIC18. You also should probably find a read a basic I2C tutorial.

PIC I2C slave ack on data

I am looking into the I2C protocol for PIC16F88X.
What I would like to do, is to enable an I2C slave to either ACK or NACK depending on the data received on the I2C.
The PIC can ACK or NACK on the I2C address sent on the line, but from what I've read it will always ACK on the subsequent received bytes. Is that correct?
In the following communication:
Start - I2c_Addr+write/ACK - Register_value/Nack
I'd like the slave to be able to Ack or Nack depending on the value in Register_value. If the slave does not understand Register_value, it should not Ack.
Could someone please either confirm that this is not possible, or tell me how to do it?
Assuming your using the MSSP peripheral
short answer: What your asking for is not probably possible with a PIC, at least without bit banging I/O lines. The reason is that ack / nack is checked on the 9th clock edge and the SSPIF interrupt is not fired until the end of the 9th clock. You could attempt to repeatedly check the BF bit as it is set as soon as the data byte is shifted into the I/O register(8th clock). If you can pull off a comparison and set the SSPOV bit before the 9th clock cycle this should generate a NACK, this is quite sketchy if you have any interrupts running.
longer answer: it sounds like your attempting to validate if the data byte the slave receives is valid or not using ack. personally i wouldn't do this, ack is to signal the integrity of the line, not verify data integrity. If the device is a slave the master by definition must know exactly how it is to work and can check the validity of the byte before pushing it out on the I2C lines. In such cases i assume you also have control over the I2C master's code, use one common header file that defines all the commands or valid data bytes that can be sent to avoid mismatches in the code.
If you must guarantee the proper byte was sent for some reason, have the master ask the slave for a response byte, have the slave return a code indicating the result of the previous transfer.
If your intent is to guarantee the integrity of the I2C line, none of these approaches really work. Your only option would be to send a bulk of a bytes at boot or periodically with a CRC and check that it matches on the slave. Generally I2C lines will either work or not, they are low speed, generally have short traces and have high allowable bus capacitance, if they arn't working you won't see any ack's at all.
My guess is no IF the I2C hardware is built-in to the PIC. All of the hardware solutions I've worked with have a state machine that can't help but ACK the second byte unless there's something wrong with the transmission (missing a bit for instance). You'd be better off making your own I2C implementation in software with bit-banging and an open-collector buffer for the ACK. Then you can do anything you want. It won't be I2C standard, so watch out if you put any devices on the bus that aren't working to your specifications. I'm not sure offhand but I think for any standard I2C device if it doesn't receive an ACK it may retransmit the data or just fault since it isn't sure who has control of the bus after a failure (signified by a NAK).