ADC MCP3561 not returning conversion values - spi

I've come here as a last resort.
I'm using this MCP3561 with no external clock(MCLK) and not using the interrupt(irq) (both floating).
DATASHEET
I originally tried to run the fast command to get the adcdata but it came back all 0.
I then tried to to set up all the config bits accordingly and still when reading the adcdata back it returns all 0's for the data. But on the read all address's incrementally I can see the data from the config's just fine.
t_buf[0] = 0b01110110; //slaveaddr + lockregister + wr
t_buf[1] = 0b10100101; // wr 0xa5 to unlock writing to registers
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_9, 0);
HAL_SPI_Transmit(&hspi1, t_buf, 2, 1000); //unlock resgisters
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_9, 1);
t_buf[0] = 0b01000110; //slave address - reg address - write
t_buf[1] = 0b01100011; //config 0
t_buf[2] = 0b00011100; //config 1
t_buf[3] = 0b10101011; //config 2
t_buf[4] = 0b11000000; //config 3 - bit 4-5 is data_format[1:0]
t_buf[5] = 0b00100000; //irq register
t_buf[6] = 0b00000001; //mux
t_buf[7] = 0b00000000; //7-8-9 scan register
t_buf[8] = 0b00000000;
t_buf[9] = 0b00000000;
t_buf[10] = 0b00000000; //10-11-12 timer delay value
t_buf[11] = 0b00000000;
t_buf[12] = 0b00000000;
t_buf[13] = 0b00000000; //13-14-15 offset calibration
t_buf[14] = 0b00000000;
t_buf[15] = 0b00000000;
t_buf[16] = 0b10000000; //16-17-18 gain calibration //0x80 is default 1x gain
t_buf[17] = 0b00000000;
t_buf[18] = 0b00000000;
t_buf[19] = 0b10010000; //19-20-21 reserved should be set at 0x90
t_buf[20] = 0b00000000;
t_buf[21] = 0b00000000;
t_buf[22] = 0b01010000; // reserved set at 0x50
t_buf[23] = 0b00000000; // lock register 0xa5 unlock anything else lock
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_9, 0);
HAL_SPI_Transmit(&hspi1, t_buf, 23, 1000);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_9, 1);
My read function:
float Get_ADC(void){
float val;
float sensor_val;
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_9, 0); //pull down cs line on adc to enable spi on chip
t_buf[0] = 0b01000011;
t_buf[1] = 0b00010000;
//HAL_SPI_TransmitReceive(&hspi1, t_buf, r_buf, 3, 1000);
HAL_SPI_Transmit(&hspi1, t_buf, 1, 1000);
HAL_SPI_Receive(&hspi1, r_buf, 28, 1000);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_9, 1); //return cs line to high to disable spi on chip
return(sensor_val);
and the data i read:
r_buf[0] uint8_t 0 '\0'
r_buf[1] uint8_t 0 '\0'
r_buf[2] uint8_t 0 '\0'
r_buf[3] uint8_t 99 'c'
r_buf[4] uint8_t 28 '\034'
r_buf[5] uint8_t 171 '«'
r_buf[6] uint8_t 192 'À'
r_buf[7] uint8_t 48 '0'
r_buf[8] uint8_t 1 '\001'
r_buf[9] uint8_t 0 '\0'
r_buf[10] uint8_t 0 '\0'
r_buf[11] uint8_t 0 '\0'
r_buf[12] uint8_t 0 '\0'
r_buf[13] uint8_t 0 '\0'
r_buf[14] uint8_t 0 '\0'
r_buf[15] uint8_t 0 '\0'
r_buf[16] uint8_t 0 '\0'
r_buf[17] uint8_t 0 '\0'
r_buf[18] uint8_t 128 '\200'
r_buf[19] uint8_t 0 '\0'
r_buf[20] uint8_t 0 '\0'
r_buf[21] uint8_t 144 '\220'
r_buf[22] uint8_t 0 '\0'
r_buf[23] uint8_t 0 '\0'
r_buf[24] uint8_t 80 'P'
r_buf[25] uint8_t 165 '¥'
r_buf[26] uint8_t 0 '\0'
r_buf[27] uint8_t 12 '\f'
r_buf[28] uint8_t 0 '\0'
r_buf[3] returns the written config0 and .... ends with r_buf[28] the lock register.
r_buf[0],1,[2] should be returning my 24bit data and no matter what combination of config settings it will always return 0. I currently have a photometric diode attached to the ch0-ch1 respectivly. It is on a printed pcb attached to a stm32l412 chip with spi_mode(1,1).
My current assumption is that the adc never leaves shutdown/sleep mode and will not do any conversions.
-Ross

It looks like you use STM32 HAL.
I found that after HAL_SPI_Transmit(), I have to call HAL_SPIEx_FlushRxFifo(&hspi1); before the next SPI operation. This is a quirk of the STM32 HAL. Alternatively, HAL_SPI_TransmitReceive() works without the flush call.
Also, your call HAL_SPI_Transmit(&hspi1, t_buf, 1, 1000); uses buffer size 1, but you previously initialized two bytes of t_buf so I guess you want to send two bytes.
To separate if the ADC or the SPI is the problem, you can try to read the internal temperature of the ADC; by reading between channels MCP3564_REGISTER_MUX_VIN_PLUS_TEMP_P and MCP3564_REGISTER_MUX_VIN_MINUS_TEMP_M (and then convert according to datasheet section 5.1.2 and figure 2-32 or 2-33).

I had the same issue, also STM32 with HAL.
Turns out you have to either pull up IRQ line to DVDD or turn on internal pullup by setting IRQ[2] register bit to 1. This is briefly mentioned in datasheet section 3.4 as
When the IRQ pin is in High-Z mode, an external
pull-up resistor must be connected between DVDD and
the IRQ pin.

Related

STM32 USB Tx Busy

I have an application running on STM32F429ZIT6 using USB stack to communicate with PC client.
MCU receives one type of message of 686 bytes every second and receives another type of message of 14 bytes afterwards with 0.5 seconds of delay between messages. The 14 bytes message is a heartbeat so it needs to replied by MCU.
It happens that after 5 to 10 minutes of continuous operation, MCU is not able to send data because
hcdc->TxState is always busy. Reception works fine.
During Rx interruption, application only adds data to ring buffer, so that this buffer is later serialized and processed by main function.
static int8_t CDC_Receive_HS(uint8_t* Buf, uint32_t *Len) {
/* USER CODE BEGIN 11 */
/* Message RX Completed, Send it to Ring Buffer to be processed at FMC_Run()*/
for(uint16_t i = 0; i < *Len; i++){
ring_push(RMP_RXRingBuffer, (uint8_t *) &Buf[i]);
}
USBD_CDC_SetRxBuffer(&hUsbDeviceHS, &Buf[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceHS);
return (USBD_OK);
/* USER CODE END 11 */ }
USB TX is also kept as simple as possible:
uint8_t CDC_Transmit_HS(uint8_t\* Buf, uint16_t Len) {
uint8_t result = USBD_OK;
/\* USER CODE BEGIN 12 */
USBD_CDC_HandleTypeDef hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceHS.pClassData;
if (hcdc-\>TxState != 0)
{
ZF_LOGE("Tx failed, resource busy\\n\\r"); return USBD_BUSY;
}
USBD_CDC_SetTxBuffer(&hUsbDeviceHS, Buf, Len);
result = USBD_CDC_TransmitPacket(&hUsbDeviceHS);
ZF_LOGD("TX Message Result:%d\\n\\r", result);
/ USER CODE END 12 \*/
return result;
}
I'm using latest HAL Drivers and software from CubeIDE (1.27.1).
I have tried expanding heap min size from 0x200 to larger values but result is the same.
Also Line Coding is set according to what recommended values:
case CDC_SET_LINE_CODING:
LineCoding.bitrate = (uint32_t) (pbuf[0] | (pbuf[1] << 8) | (pbuf[2] << 16) | (pbuf[3] << 24));
LineCoding.format = pbuf[4];
LineCoding.paritytype = pbuf[5];
LineCoding.datatype = pbuf[6];
ZF_LOGD("Line Coding Set\n\r");
break;
case CDC_GET_LINE_CODING:
pbuf[0] = (uint8_t) (LineCoding.bitrate);
pbuf[1] = (uint8_t) (LineCoding.bitrate >> 8);
pbuf[2] = (uint8_t) (LineCoding.bitrate >> 16);
pbuf[3] = (uint8_t) (LineCoding.bitrate >> 24);
pbuf[4] = LineCoding.format;
pbuf[5] = LineCoding.paritytype;
pbuf[6] = LineCoding.datatype;
ZF_LOGD("Line Coding Get\n\r");
break;
Thanks in advance, any support is appreciated.
I don't know enough about the STM32 libraries to really check your code, but I suspect you are forgetting to read the bytes transmitted by the STM32 on PC side. Try opening a terminal program like PuTTY and connecting to the STM32's virtual serial port. Otherwise, the Windows USB-to-serial driver (usbser.sys) will eventually have its buffers filled with data from your device and it will stop requesting more, at which point the buffers on your device will fill up as well.

CH340 handshaking using libusb

Does anyone know how to read CTS pin of CH340 using libusb_control_transfer? I can write to RTS using following code:
libusb_control_transfer( handle, // libusb_device_handle * dev_handle
CTRL_OUT, // uint8_t bmRequestType
0xA4, // uint8_t bRequest
1<<6, // uint16_t wValue
0, // uint16_t wIndex
NULL, // unsigned char *data
0, // uint16_t wLength
1000); // unsigned int timeout
So I think it might be possible to do the same to read state of CTS pin?
Thanks to kernel driver source code:
libusb_control_transfer( handle,
CTRL_IN,
0x95,
0x0706,
0,
&data[0],
2,
1000);

STM32L072CZTx mpu6050 i2c No ACK after some successfull transmitting

i made a customboard with a MPU-6050 & STM32L072CZTx on it.
My problem is, that the MPU-6050 doesn't ack after some successfull transmision.
I have two 4,7k pull-ups on SCL and SDA.
Restarting the MCU doesn't fix it.
I have to unplug the power to get the MPU to ACK again for some transmision.
I am using STM32 HAL and added 2 images for clarification.
What i tried:
Replaced MPU6050
lowered I2C frequenzy
much more...
Thanks for your help.
HAL_StatusTypeDef writeBytes(uint8_t deviceAdd, uint8_t regAdd, uint8_t *data, uint8_t size)
{
uint8_t buffer[size + 1];
buffer[0] = regAdd;
memcpy((buffer + 1), data, size);
return HAL_I2C_Master_Transmit(&hi2c1, deviceAdd << 1, buffer, size + 1, I2C_TIMEOUT);
}
HAL_StatusTypeDef readBytes(uint8_t deviceAdd, uint8_t regAdd, uint8_t *data, uint8_t size)
{
return HAL_I2C_Mem_Read(&hi2c1, (uint16_t)(deviceAdd << 1), (uint16_t)regAdd, I2C_MEMADD_SIZE_8BIT, data, size, I2C_TIMEOUT);
}
Oscilloscope
MPU6050 schematic

PIC24H Uart send only 4 bits correct - need to split

I am working with the explorer16/32 evb and trying to send data to UART.
I tried UART1, UART2 with and without interrupts and got the same problem all the time.
It appeared that in order to send 1 byte I need to split it to two 4 bits with shift
code:
#define FCY 16000000
#define BAUDRATE 9600
#define BRGVAL ((FCY/BAUDRATE)/16)-1
U2MODE = 0;
U2STA = 0;
U2MODEbits.STSEL = 0; // 1-Stop bit
U2MODEbits.PDSEL = 0 ; // No Parity 8 bit data
U2MODEbits.ABAUD = 0; // Auto-Baud Disabled
U2MODEbits.BRGH = 1; // High Speed Mode
U2MODEbits.URXINV = 0;
U2STAbits.UTXINV = 0;
U2BRG = BRGVAL; // Baud Rate Setting for 9600
U2MODEbits.UARTEN = 1; //Enable UART module
U2STAbits.UTXEN = 1; //Enable UART TX
unsigned char putU2(unsigned char c)
{
while (U2STAbits.TRMT == 0)
{
}
while ( CTS);
while ( U2STAbits.UTXBF);
U2TXREG = c & 0xF;
U2TXREG = (c >> 4) & 0xF;
return c;
}
If I am sedning that data splited to 4 bits I can see the data correct on the PC( c# serial port application)
But it should not be split into two writes to U2TXREG.
I am not 100% sure that the FCY is 16000000 but this is the only value that give me reasonable result.
What could be the problem?
For PIC24H, in UART high speed mode ( BRGH = 1 ) to get correct value of BRGVAL you need to divide by 4, not 16. Change the formula on line 3. Also, it is helpful to be 100% sure about clock rate; if you didn't change configuration bits it is likely 8 MHz, not 16.

How to tie together an HID USB descriptor and the USB frames actually sent on the bus

I'm trying to decipher data sent on the USB bus by an HID device (an Eaton power supply to be precise)
Using Wireshark, I can capture the USB traffic. When the device is connected, I can see the HID descriptor being sent. I can parse it alright, and thanks to an external reference (http://networkupstools.org/protocols/mge/NUT_MGE_USB_Devices_Draft_AA.pdf and http://www.usb.org/developers/docs/devclass_docs/pdcv10.pdf), I've got some info regarding the different fields of the descriptor.
However, I can't seem to link the descriptor to the data inside the frames I actually capture with Wireshark: I can't really make out any clear header or pattern in the messages, tied to the descriptor.
In this case, I see quite a bunch of URB Control Response messages, which probably contain the data I want, but which message contains which info is unclear.
Does anyone have some sort of method to reverse-engineer and parse the data sent by a USB HID device ?
Thanks
I wrote a bit of code a while back to help me decode HID report descriptors and to create C language structure definitions to describe each report. What I would do is:
capture the USB data using Wireshark
filter on "usb.request_in"
select the "GET DESCRIPTOR Response HID Report" packet
right-click the "HID Report" and choose "Copy" and "...as a Hex Stream"
Now run the decoding software and paste the hex stream after the "-c" option. For example:
rexx rd.rex -c 05010906a101854b050719e029e7250175019508810275089501810326ff0019002aff0081007501950305081901290325019102750595019103c005010902a1010901a100854d09301581257f750895018106c0c0
It will by default print the C-structures (see below). If you want to also decode the HID report descriptors then use the "-d" option.
//--------------------------------------------------------------------------------
// Keyboard/Keypad Page inputReport 4B (Device --> Host)
//--------------------------------------------------------------------------------
typedef struct
{
uint8_t reportId; // Report ID = 0x4B (75) 'K'
// Collection: Keyboard
uint8_t KB_KeyboardKeyboardLeftControl : 1; // Usage 0x000700E0: Keyboard Left Control, Value = 0 to 1
uint8_t KB_KeyboardKeyboardLeftShift : 1; // Usage 0x000700E1: Keyboard Left Shift, Value = 0 to 1
uint8_t KB_KeyboardKeyboardLeftAlt : 1; // Usage 0x000700E2: Keyboard Left Alt, Value = 0 to 1
uint8_t KB_KeyboardKeyboardLeftGui : 1; // Usage 0x000700E3: Keyboard Left GUI, Value = 0 to 1
uint8_t KB_KeyboardKeyboardRightControl : 1; // Usage 0x000700E4: Keyboard Right Control, Value = 0 to 1
uint8_t KB_KeyboardKeyboardRightShift : 1; // Usage 0x000700E5: Keyboard Right Shift, Value = 0 to 1
uint8_t KB_KeyboardKeyboardRightAlt : 1; // Usage 0x000700E6: Keyboard Right Alt, Value = 0 to 1
uint8_t KB_KeyboardKeyboardRightGui : 1; // Usage 0x000700E7: Keyboard Right GUI, Value = 0 to 1
uint8_t pad_2; // Pad
uint8_t KB_Keyboard; // Value = 0 to 255
} inputReport4B_t;
//--------------------------------------------------------------------------------
// LED Indicator Page outputReport 4B (Device <-- Host)
//--------------------------------------------------------------------------------
typedef struct
{
uint8_t reportId; // Report ID = 0x4B (75) 'K'
// Collection: Keyboard
uint8_t LED_KeyboardNumLock : 1; // Usage 0x00080001: Num Lock, Value = 0 to 1
uint8_t LED_KeyboardCapsLock : 1; // Usage 0x00080002: Caps Lock, Value = 0 to 1
uint8_t LED_KeyboardScrollLock : 1; // Usage 0x00080003: Scroll Lock, Value = 0 to 1
uint8_t : 5; // Pad
} outputReport4B_t;
//--------------------------------------------------------------------------------
// Generic Desktop Page inputReport 4D (Device --> Host)
//--------------------------------------------------------------------------------
typedef struct
{
uint8_t reportId; // Report ID = 0x4D (77) 'M'
// Collection: Mouse Pointer
int8_t GD_MousePointerX; // Usage 0x00010030: X, Value = -127 to 127
} inputReport4D_t;
Now that you have a clear idea of the possible reports that may be flowing, you can go back to your Wireshark trace (still filtered on "usb.request_in") and select "URB_INTERRUPT in" packets. The "Leftover Capture Data" should contain the payload as described by one of the C structures.
Hope this helps.