Problem with I2C communication with sensor TSL2572 and the board STM32L152C-DISCOVERY - c

I'm trying to communicate between board and sensor with i2c but I can't quite figure out how to do it. in the datasheet i checked all the registers and how to access them and the address of the sensor. once this was done I retrieved the HAL_I2C_Mem_Write and HAL_I2C_Mem_Read functions from the HAL library for reading and configuration. for example, to enable the sensor clock and make the ADC work I have to write raise the last two bits of the byte of the register 0x00, so I wrote the following line:
buf[0]=0x03;
HAL_I2C_Mem_Write(&i2c2, address, 0x00, 1, buf, 1, 1000);
then when I go to read the register with HAL_I2C_Mem_Read I get the value 0. the same goes for the others, for example if I read the register 0x12 I get the decimal value of 0x12 and not its content. Where am I doing wrong?
I add that I have checked the correctness of the hardware connections between the card and the sensor.

Related

Read non conventional ADC with STM32F3

I'm attempting to interface an STM32F303 Nucleo with an AD7748-4 ADC. Datasheet for the ADC:
https://www.analog.com/media/en/technical-documentation/data-sheets/ad7768-7768-4.pdf
The issue is, the ADC DOES NOT output the converted value through the SPI port, but rather employs a Data Ready Signal (DRDY), a Data Clock (DCLK), and a combination of 4 Data Outputs (DOUT0-DOUT3). The output streams 96 bits serially through one wire if I set it up that way, but timing is critical in my application and I need to clock the data in using DOUT0 to DOUT2, which would each output 32 bits. If I were serially streaming the data, I could trick the SPI port into reading it, but I'm not. The ADC is running at 20MHz, so DCLK will be operating at the same frequency. The Nucleo runs at a maximum of 72MHz, but when the DAM is utilized, it sets the clock to 64MHz.
In the STM manual, it describes a "GPIO port input data register (GPIOx_IDR) (x = A..H)" as being a read only register - my understanding is that the lower 16 bits can store an inputted value up to 16 bits (most likely for memory data R/W) - so the question is, how can I configure the GPIO to read in the data? I'm at a slight impass here. My instinct tells me that the Nucleo may not be fast enough to read the data coming from the ADC... Any ideas? All being written in C/C++ basically bare metal... I'm new to the Nucleo, haven't written code in 4 years - pardon any lapse in knowledge...
If DCLK works at 20Mhz, the uC is obviously not fast enough (you have about 3 instructions between each cycle, so even assembly language would be difficult to implement...). As I am not familiar with the stm architecture, I can only suggest a trick that will maybe spark some ideas in your head. Rather than using a crystal for the ADC, use a timer from the STM that is connected to an output pin, and clock the ADC using that pin (MCLK). When configuring the ADC using spi, idle mode, etc. you can leave this clock signal at 20Mhz. But when you need a sample from the ADC, stop the STM timer and clock the ADC "manually". (you practically control the DCLK signal). After your conversion routine is over, restart the timer at 20Mhz.

Create virtual uart on stm32 microcontroller

I need to create a virtual uart port on a stm32 microcontroller. The pins are given and can be changed to timer input channels. The recieving signal is going to be modulated in current and voltage and i need to detect both. Those two pins can not be assigned to a uart. Does somebody has a tutorial or something, that can lead me in the right direction? I just started programming microcontrollers and i am still strugeling with all the timer, interrupts and details stuff.
If we are talking aobut baudrates for small (9600), then you can achieve this with timer and EXTI.
On EXTI set pin to rising and falling edge and between each IRQs check timer value.
If value is greater than start and stop condition time, you failed, else you have to check time spent for EXTi and calculate whether you received 10101010 or 11001100 or any other combination.
For TX mode, use timer for precise interrupts at bit slice for UART output data and create state machine for data output bit by bit.
Another option is to use SPI as virtual UART.

Where can I find the device specific JTAG instructions for Cortex-M3?

I'm trying to communicate with a Cortex-M3 based microcontroller (LPC1769) through JTAG. I already have the hardware required, and have managed to get an example program to work, but to progress further, I need to know the device-specific JTAG instructions that are available in this case. I have read the corresponding section of the Cortex-M3 technical reference manual (link), and all that told me, was that the device uses a standard CoreSight debug port. In particular, I'd like to read the device ID with the IDCODE instruction. Some sites suggest, that the IDCODE might be b0001 or b1110 for this device, but neither of them seem to work. b0001 seems more likely to me, as that's the value I read from the IR after the TAP has been reset.
I also considered the possibility, that the instruction I'm using is correct, and I'm just not reading the device ID register properly. I'm using an FTDI cable with the FT232H chip, and the application I'm using is based on FTDI's AN129 example code (link), using MPSSE commands. I use the 0x2A command to clock data in from the TAP, the 0x1B command to clock data out to the TAP, and the 0x3B command to do both simultaneously. If anyone could provide some insight, as to what I'm doing wrong (or whether I'm using the right IDCODE instruction at all), that would be much appreciated.
*EDIT:
I made some progress, but the IDCODE instruction still eludes me. I managed to read the Device ID after setting the TAP controller to Test-Logic-Reset state (which loads the IDCODE instruction in the IR). However, I tried all possible (16) instructions, and while some of them resulted in different reads from the DR, none loaded the Device ID register.
This is the function I use to insert the instruction, once the TAP controller is in Shift-IR state:
int clockOut(FT_HANDLE* ftHandle, BYTE data, BYTE length)
{
FT_STATUS ftStatus = FT_OK;
BYTE byOutputBuffer[1024]; // Buffer to hold MPSSE commands and data to be sent to the FT232H
DWORD dwNumBytesToSend = 0; // Index to the output buffer
DWORD dwNumBytesSent = 0; // Count of actual bytes sent - used with FT_Write
byOutputBuffer[dwNumBytesToSend++] = 0x1B;
// Clock data out through Shift-DR
byOutputBuffer[dwNumBytesToSend++] = length - 1;
// Number of clock pulses = (length - 1) + 1; This way, the length given as the parameter of the function is the actual number of clock pulses.
byOutputBuffer[dwNumBytesToSend++] = data;
// Shift out data
ftStatus = FT_Write(*ftHandle, byOutputBuffer, dwNumBytesToSend, &dwNumBytesSent);
// Send off the TMS command
return ftStatus;
}
The length parameter is set to 4, and the data parameter is set to 0x0X (where I tried all possible values for X, neither of which led to success)
I managed to get it to work. The problem was, that when I sent out 4 bits to the IR, it in fact received 5. After finishing the transmission, the next rising edge of TCK was supposed to change the state of the TAP controller, but as it was still in the Shift-IR state, it not only changed the state, but also sampled the TDI, and did another (fifth) shift. To countermand this, I only shifted the lower 3 bits of the instruction, and then used a 0x4B MPSSE command, to simultaneously clock out a TMS signal (to change the state), and send out the MSB of the command.

Memory mapped ADC on DE1-SoC using HPS (hard-core processor)

I am unable to read from or write to the AD7928 analog to digital converter (ADC) on the DE1-SoC (Rev. F) development board.
I have the datasheets for the board and the ADC. I am using a mix of custom IP and pre-made hardware components. I have implemented the LEDs, push buttons, and 7-segment displays in Qsys along with the ADC. Base addresses and ranges are set for the memory space of each component. I am controlling the hardware with a C program running in Linux on the dev board. Using a virtual address and offset, I can control all the aforementioned components except the ADC.
The datasheet for the ADC shows 8 registers for reading and 2 for writing. The ADC is set up in Qsys to use one channel (channel 0) out the 8 channels available, running at 12.5MHz. The memory range in Qsys shows correctly that there are 32bytes of addressing assigned to the ADC (8 registers at 4 bytes each). Two of the registers share a read and write command.
Here are the pointers I use for writing the Auto Enable command and reading the 12-bit temperature from channel 0 of the ADC:
// Set ADC to automatically update (write to register offset 4)
*(uint32_t *)(h2p_lw_adc_addr + 4) = 1;
// Read channel 0 from the ADC (read from register offset 0)
temp_in = *(uint32_t *)h2p_lw_adc_addr;
I use the same pointer set-up with the other components, which all work.
I looked at the soft-core processor set-up for the ADC and it has a .h file that contains a command to turn the ADC on, but it seems the hard-core processor systems does not have that command.
Is there some other set-up required for the ADC to be able to use it with the HPS (hard-core processor sys)? The ADC datasheet only shows the 8 registers for control and I have tried both the Auto Enable and Begin Conversion modes. The command registers are shown below.
Command registers for ADC

Sparkfun SC16IS750 does not work on Raspberry Pi

I'm connecting a SC16IS750 spi-2-uart bridge to the Raspberry Pi 2 in order to increase the number of uart ports. The product is a breakout board made by Sparkfun (https://www.sparkfun.com/products/9981), utilizing the SC16IS750 chip (http://www.nxp.com/documents/data_sheet/SC16IS740_750_760.pdf). I use the BCM2835 library by Mike McCauley to access SPI.
The problem is, whichever register I try to read, I invariably get back 0xff. For example,
uint8_t tx[2];
tx[0] = 0x07 << 3 | 0x80; // SPR register
tx[1] = 0x00;
uint8_t rx[2] = {0x00, 0x00};
// perform duplex write operation
bcm2835_spi_transfernb(tx, rx, 2);
rx[0] and rx[1] returns 0xff. It doesn't matter which register I try to read, the result is the same.
The breakout board already grounds the reset pin. I connect the CS pin to SSEL1, CLK to GPIO11, SI to GPIO10, SO to GPIO9, and SPI/I2C to ground. I tried with another chip, same response. SPI works fine since I also use it successfully with another peripheral.
Any idea on what I should try next?
Turns out the problem is the clock divider. Setting the SPI clock divider to 256 and above
bcm2835_spi_setClockDivider(BCM2835_SPI_CLOCK_DIVIDER_256)
resolved the problem.

Resources