I bought STEVAL-MKSBOX1V1 of ST and wanted to write my own library to create a BLE application.
The BLE module on board is SPBTLE-1S which mounts BlueNRG-1, I wrote my own firmware in order to communicate using SPI protocol.
After resetting the module using the pin I send a read request from MCU to the BLE module,
HAL_GPIO_WritePin(SPI1_CS_GPIO_Port,SPI1_CS_Pin,0);
HAL_SPI_TransmitReceive(&hspi2,tx,rx,5,1);
HAL_GPIO_WritePin(SPI1_CS_GPIO_Port,SPI1_CS_Pin,1);
I send:
{0x0b,0x00,0x00,0x00,0x00}
I get:
{0xff,0x08,0x00,0x06,0x00}
So apparently nothing good because the first byte is 0xff and not 0x02 (right?), but the 4th bit(0x06) should indicate the amount of data inside the read buffer.
If I read 6 bytes I get
{0x04,0xff,0x03,0x01,0x00,0x01}
And according to AN4494 It is exactly what I should read after the reset event on the module.
Then my question is why I keep getting {0xff,0x08,0x00,0x06,0x00} and not something like {0x02,....}?
Is there anything related to BlueNRG1 that is different from BlueNRG2? (It is so hard to find good documentation)
If anyone has some experience on SPI communication with this module I would like to have a bit of consulting.
Thanks in advance
{0xff,..} would be correct.
AN4494 is for BlueNRG-MS, the 5-byte SPI header for MISO is: {Ready, WBufLen, 0x00, RBufLen, 0x00}. In BlueNRG-1 and BlueNRG-2, that SPI header has been modified to: {0xff, CmdLen0, CmdLen1, DataLen0, DataLen1}, in order to support ACI packets with length more than 127 bytes in a single SPI transaction. The first byte in the header is fixed to 0xff.
Unfortunately currently there is no document describing the modification. You may need to refer to DTM SPI sample project to know the details.
In your transaction, if executing a Read command and continuing to read MISO for the 6 byte data:
{0xff,0x08,0x00,0x06,0x00},{0x04,0xff,0x03,0x01,0x00,0x01}
That is a ACI Blue initialized event, saying firmware has started properly. That can be parsed:
Header
0x0006: 6 bytes (data) is available to be read
Data
0x04: HCI event packet
0xFF: ACI (vendor specific) event
0x03: parameter length
0x10 0x00: event = 0x0001, which is ACI_BLUE_INITIALIZED_EVENT
0x01: reason code = 1, which means firmware started properly
Related
In my project, I am using Winbond W25Q64 64-MB Serial flash, When i read datasheet of this serial flash there is two type:
SPI(W25Q64 FLASH ID :- 0xEF4017) and QPI(W25Q64FV FLASH ID :- 0xEF6017).
I know SPI very well, but first time i heard about QPI. So i have some Questions-
1.What is the difference's between SPI and QPI?
2.Can i use QPI communication type Flash(using SPI)?
3.What is the main feature's of QPI and what is QPI(a Communication Protocol or something else)?
Description of the QPI protocol is part of the datasheet (I have added the link into your question).
Judging from the description there, it does use four data lines for I/O (in contrast to SPI where one line is designated for input and another for output), thus saving clock cycles (compared to standard SPI) as one byte can be transfered in 2 cycles only. Available commands seems to be different too compared to SPI mode.
This chip supports some "extended" SPI modes (called Dual and Quad SPI) where more data lines are used for sending data to master. These are triggered by standard SPI command, but data transfer differs. See the details in the datasheet.
It is not compatible with "standard" SPI, and I am not sure if there is any common MCU supporting this mode. It looks similar to the SD card / SDIO, but I have no idea how much is it (dis)similar.
Yes, you can. The standard SPI (one input and one output data line) seems to be the default interface. The extended SPI modes are used in response to particular SPI commands only and the QPI mode has to be explicitly enabled by respective SPI command (see figure 3 in page 12).
In addition:
Quad SPI and QPI instructions require the non-volatile Quad
Enable bit(QE) in Status Register-2 to be set. When QE=1,
the /WP pin becomes IO2 and /HOLD pin becomes IO3.
...
QE bit is required to be set to a 1 before issuing an “Enable QPI
(38h)” to switch the device from Standard/Dual/Quad SPI to QPI,
otherwise the command will be ignored. When the device is in QPI mode,
QE bit will remain to be 1. A “Write Status Register” command in QPI
mode cannot change QE bit from a “1” to a “0”.
Advantage is faster data transfer at the same clock frequency. Details of the protocol are well described in the datasheet including timing plots etc.
This is driving me nuts for a couple of days now, so maybe you guys can give me some insights into what is going wrong.
I'm trying to read some data from an EEPROM (24LC16B) with an STM32(F0), but it just doesn't let me. I've tried an Arduino, which worked and does still work, so I do know that the wiring is correct.
This is my function to read the EEPROM data. (It is cut down to the very basis, just for testing): (Pastebin of my I2C_setup function)
uint16_t readEEPROMData(uint16_t deviceAddress, int memAddress){
// Wait while I2C peripheral is not ready
I2C_WaitForFlag(I2C_ISR_BUSY);
// Start I2C write transfer for 2 bytes, do not end transfer (SoftEnd_Mode)
I2C_TransferHandling(I2C1, 0xA2, 2, I2C_SoftEnd_Mode, I2C_Generate_Start_Write);
I2C_WaitForFlag(I2C_ISR_TXIS);
// For testing purpose, be sure to generate a stop command...
I2C_TransferHandling(I2C1, 0xA2, 0, I2C_AutoEnd_Mode, I2C_Generate_Stop);
return I2C_COMM_STATUS;
}
Here's an pastebin of the Arduino library I used.
I've used a logic analyzer to see how the communication is going, and now I really don't understand it. Here's a printscreen of the working Arduino version:
And here's a printscreen of the STM32 communication:
Logic analyzer exports (viewable with Saleae Logic)
As you can see, I'm using the same address (although I had to use 0xA2 with the STM32), and there are no weird things happening, besides the NACK. So what could possible be wrong?
Confirm if all bus timing requirement are satisfied.
Confirm if their is adequate delay after every write cycle (5 mS)
Confirm is bus capacitance falls under permissible limit of I2C (400 pF - Theoretically).
Confirm if the correct VCC is supplied
As mentioned by you are interfacing EEPROM with MCU using cable you need to conform on capacitance.
You can use an oscilloscope to check if their are any distortion in waveform. You can use a LCR meter to check the capacitance.
Try reducing bus speed 25kHz to 50 kHz and check waveform.
Try increasing the strength of pull resister.
The problem with the wrong VCC capacity (4.2v instead of 5v for example) is, that the timing can be different to. (not fully verified, but it fixed the problem)
I am trying to communicate with SMC LEC6 Servo motor controller via Delphi 7-TComPort Library. I have read related questions TComPort and Modbus. My question is if I want to send a massage containing 8 bytes, how can I specify the stop-bit/start-bit values ? and Do I need to send each byte as a packet and the stop-bit separately or it will be done automatically by the library ?
The start bit cannot be selected and this bit will be added to each byte automatically by your RS485 or RS232 hardware.
The stop bit type you may select in the component properties (e.g. 1 stop bit). This bit will be added automatically too.
I'm trying to do something really simple and I'm having a bit of trouble getting it to work. I'm working with the MPL3115A2 Altitude/Pressure Sensor and a pic32 uC32 board, and I'm trying to communicate between the two using I2C. (uC32 board is similar enough to arduino that it's practically the same in terms of coding).
I'm using the wire library and I'm simply trying to read register 0x0C from the MPL3115A2, which should give me the device ID.
Here's a code snippet (the define is at the top of the code and the rest is in the main loop):
#define barAddress 0x60
Wire.beginTransmission(barAddress);
Wire.send(0x0C);
Wire.endTransmission();
Wire.requestFrom(barAddress, 1);
uint8_t a = Wire.receive();
Serial.println(a, HEX);
So I start the transmission with address 0x60 (From the datasheet: The standard 7-bit I2C slave address is 0x60 or 1100000. 8-bit read is 0xC1, 8-bit write is 0xC0.). Then I send 0x0C because that's the register I want to access. I then end transmission, and request 1 byte from address 0x60, receive that bit into a 8-bit variable, then print it.
The problem I run into is that when I print it, I just get 0. I don't get the device ID, just 0. No matter what register I try to read, I get 0.
I've been banging my head against a wall for the past few days trying to get this to work. I've attached something I've captured with a logic analyzer, as well as a list of registers from the datasheet of the MPL3115A2 that I've been trying to access.
Using a logic analyzer I can see the clock and data lines. The clock seems normal and the data line gives me the following:
START
Write['192'] + ACK
'12' + ACK
STOP
START
Read['193'] + ACK
'0' + NAK
STOP
This all seems correct to me (192 and 193 come from 8-bit write and read being 0xC0 and 0xC1), except for the '0'. I should be getting the device ID, not 0.
Thanks for any help with this!
You should look at Freescale's app note AN4481, which is referred to by the datasheet. Page 5 shows the single-byte read operation which is what you are doing, except that the register address write must not be followed by a STOP but instead uses a REPEATED-START.
I'm not familiar with the Wire library but it look like all you need to do is remove the Wire.endTransmission(); between the send and requestFrom.
Hopefully, this will solve your problem.
I want to implement a serial loopback driver code in 8250.c found in /drivers/tty/serial/8250.c as found in linux-3.6.1 kernel.
I do not want to use the hardware loopback(i.e by shorting pin 2(tx) and 3(rx) of the standard serial port), instead I want to modify the 8250.c driver such that, the data from user space will travel from the "serial8250_tx_char" function directly to the "serial8250_rx_char" without going to the hardware, i.e I want to receive what is transmitted?
One possible implementation would be to put the transmission circular buffer data into the tty flip buffer, and then push this data up to the tty core so that the user space can receive it?
I want to know how to do it in the code. We can search the "rx and tx" functions mentioned above-that is where I am looking, and how will I test this, means by writing on the device file and then immediately receiving the same.
I also have a sample patch, but not sure, whether it will work.
Any help would be appreciated...
Abhijit
`## -2112,6 +2116,7 ## static int serial8250_startup(struct uart_port *port)
if (is_real_interrupt(up->port.irq))
up->port.mctrl |= TIOCM_OUT2;
+ up->port.mctrl |= TIOCM_LOOP;
serial8250_set_mctrl(&up->port, up->port.mctrl);
/* Serial over Lan (SoL) hack:
This will set UART to work in internal loop-back mode.`