Hi I 'm trying to learn how to configure this module, I setup 4 channels for read the adc value on each channel, but the results are being crossed, when I energized channel 0 the other follow that voltage, and the same happens for the others, I tried to set continuos scan, single scan but I receive the same result
void hal_entry(void)
{
uint32_t i;
g_adc0.p_api->open(g_adc0.p_ctrl, g_adc0.p_cfg);
g_uart.p_api->open (g_uart.p_ctrl, g_uart.p_cfg);
g_timer0_agt.p_api->open(g_timer0_agt.p_ctrl, g_timer0_agt.p_cfg);
g_adc0.p_api->scanCfg(g_adc0.p_ctrl, g_adc0.p_channel_cfg);
g_adc0.p_api->scanStart(g_adc0.p_ctrl);
for(;;)
{
}
}
void isr_irq_ADC000(adc_callback_args_t *p_args)
{
SSP_PARAMETER_NOT_USED(p_args);
g_adc0.p_api->read(g_adc0.p_ctrl, ADC_REG_CHANNEL_0,&val0);
g_adc0.p_api->read(g_adc0.p_ctrl, ADC_REG_CHANNEL_1,&val1);
g_adc0.p_api->read(g_adc0.p_ctrl, ADC_REG_CHANNEL_2,&val2);
g_adc0.p_api->read(g_adc0.p_ctrl, ADC_REG_CHANNEL_3,&val3);
g_adc0.p_api->scanStart(g_adc0.p_ctrl);
}
Related
I am trying to build communication between a sensor and MSP430F5438a over I2C. Trying to write a code from scratch. Not using any interrupt at this point. Now to read PartID from the sensor I'm following the steps below:
Master issues start condition, sends slave address for write(0b 1010 1110)
Master sends Register address (e.g 0xFF for part id).
Master issues repeated start condition, sends slave address for reading (0b 1010 1111)
Master reads data byte returned from the slave. (Supposed to get back 0x15 which is the PartID).
My issue is I am not getting anything back in my receive buffer. I'm probably doing something wrong in my code. But actually, don't understand where I am doing wrong. Anyone can help in it? My hardware connection is fine I hope (Checked with the sensor provider).
I'm attaching my code below: Wrote it in Code Composer Studio.
#include <msp430.h>
#include <string.h>
#define MAX30101_I2C_ADDRESS 0x57
void Clock_setup(); // default
void I2C_setup();
int readByte(char register_add);
int ID;
void main()
{
WDTCTL = WDTPW + WDTHOLD;
Clock_setup();
I2C_setup();
ID = readByte(0xFF);
}
void Clock_setup(){
P11DIR |= BIT2; // check smclk, 1MHz default
P11SEL |= BIT2; // check smclk, 1MHz default
P11DIR |= BIT0; // check aclk, 32.8KHz default
P11SEL |= BIT0; // check aclk, 32.8KHz default
}
void I2C_setup() {
P3SEL |= BIT7; // 3.7 UCB1_SDA, 5.4 UCB1_SCL
P5SEL |= BIT4;
UCB1CTL1 |= UCSWRST; // reset enable
UCB1CTL0 = UCMST + UCMODE_3 + UCSYNC; // master + I2C mode + Sync
UCB1CTL1 = UCSSEL_2 + UCSWRST; //use SMCLK + still reset
UCB1BR0 = 10; // default SMCLK 1M/10 = 100KHz
UCB1BR1 = 0; //
UCB1I2CSA = MAX30101_I2C_ADDRESS; // MAX30101 7 bit address 0x57
UCB1CTL1 &= ~UCSWRST; // reset clear
}
int readByte(char register_add){
int rx_byte;
UCB1CTL1 |= UCTXSTT+ UCTR; // Generating START + I2C transmit (write)
UCB1I2CSA = 0xAE; // MAX30101 7 bit address 0x57
UCB1TXBUF = register_add; // sending 0xFF to read the PartID
while(!(UCB1IFG & UCTXIFG)); //wait until reg address got sent
while( UCB1CTL1 & UCTXSTT); //wait till START condition is cleared
UCB1CTL1 |= UCTXSTT; //generate RE-START
UCB1I2CSA = 0xAF; // MAX30101 7 bit address 0x57
UCB1CTL1 &=~ UCTR; //receive mode
while( UCB1CTL1 & UCTXSTT); //wait till START condition is cleared
rx_byte = UCB1RXBUF; //read byte
//while(!(UCB1IFG & UCRXIFG)); //wait while the Byte has being read
UCB1CTL1 |= UCTXNACK; //generate a NACK
UCB1CTL1 |= UCTXSTP; //generate stop condition
while(UCB1CTL1 & UCTXSTP); //wait till stop condition got sent
return rx_byte;
}
I²C slave addresses have 7 bits; 0xAF or 0xAE cannot be valid. The comments already say that 0x57 is the correct value.
And you must wait for the received byte to be available (UCRXIFG) before trying to read it.
And this code lacks all error handling; you should at least check for NACK.
I have a Raspberry Pi 3B and Suptronics X920 Expansion Board which uses PCM5122 DAC. So I'm having trouble playing sounds through that board.
The config file is default except for the display configuration part:
kernel=u-boot-dtok.bin
framebuffer_depth=16
# Prevent the firmware from loading HAT overlays now that we handle pin muxing.
# ourselves. See:
# https://www.raspberrypi.org/documentation/configuration/device-tree.md#part3.4
dtoverlay=
dtparam=i2c_arm=on
dtparam=spi=on
dtparam=audio=on
# pwm and I2S are mutually-exclusive since they share hardware clocks.
dtoverlay=pwm-2chan-with-clk,pin=18,func=2,pin2=13,func2=4
dtoverlay=generic-i2s
start_x=1
# Tell U-boot to always use the "serial0" interface for the console, which is
# set to whichever uart (uart0 or uart1) is set to the header pins. This doesn't
# interfere with the uart selected for Bluetooth.
dtoverlay=chosen-serial0
# Enable skip-init on the UART interfaces, so U-Boot doesn't attempt to
# re-initialize them.
dtoverlay=rpi-uart-skip-init
# Add pin devices to the system for use by the runtime pin configuration driver.
dtoverlay=runtimepinconfig
dtoverlay=uart1
dtoverlay=bcm2710-rpi-3-b-spi0-pin-reorder
# Tell the I2S driver to use the cprman clock.
dtoverlay=bcm2710-rpi-3-b-i2s-use-cprman
# Uncomment to disable serial port on headers, use GPIO14 and GPIO15
# as gpios and to allow the core_freq to change at runtime.
enable_uart=1
core_freq=400
# Support official RPi display.
dtoverlay=i2c-rtc,ds3231
dtoverlay=rpi-ft5406
hdmi_force_hotplug=1
# Set framebuffer to support RGBA colors.
framebuffer_swap=0
# Waveshare display settings
max_usb_current=1
hdmi_group=2
hdmi_mode=87
hdmi_cvt 1024 600 60 6 0 0 0
hdmi_drive=1
This is the code for playing a sound file:
fun playSound(file: File) {
val audioEncoding = AudioFormat.ENCODING_PCM_16BIT
val sampleRate = 16000
val audioOutputFormat = AudioFormat.Builder()
.setChannelMask(AudioFormat.CHANNEL_OUT_MONO)
.setEncoding(audioEncoding)
.setSampleRate(16000)
.build()
val audioOutputBufferSize = AudioTrack.getMinBufferSize(sampleRate, audioOutputFormat.channelMask, audioEncoding)
val audioOutputDevice = findAudioDevice(AudioManager.GET_DEVICES_OUTPUTS, AudioDeviceInfo.TYPE_BUS)
val audioTrack = AudioTrack.Builder()
.setAudioFormat(audioOutputFormat)
.setBufferSizeInBytes(audioOutputBufferSize)
.setTransferMode(AudioTrack.MODE_STREAM)
.build()
audioTrack.preferredDevice = audioOutputDevice
val buffer = ByteArray(audioOutputBufferSize)
audioTrack.play()
audioTrack.setVolume(1f)
val stream = file.inputStream().buffered()
try {
while (stream.read(buffer) > 0) {
val out = audioTrack.write(buffer, 0, buffer.size, AudioTrack.WRITE_BLOCKING)
d { "audioTrack.write = $out" }
}
} catch (error: Throwable) {
e(error) { "Error playing audio $file" }
} finally {
stream.close()
}
audioTrack.stop()
audioTrack.release()
}
private fun findAudioDevice(deviceFlag: Int, deviceType: Int): AudioDeviceInfo? {
val manager = getSystemService(Context.AUDIO_SERVICE) as AudioManager
val adis = manager.getDevices(deviceFlag)
for (adi in adis) {
if (adi.type == deviceType) {
return adi
}
}
return null
}
I've tested the code with a regular Raspberry Pi audio output (which is AudioDeviceInfo.TYPE_BUILTIN_SPEAKER) and it works ok. But with AudioDeviceInfo.TYPE_BUS it just produces no sound without any errors.
I tried various config options like dtoverlay=hifiberry or dtoverlay=hifiberry-dacplus with no luck.
Please help.
It looks like you might be using some of the code for the Google Assistant sample, and you are correct to assume that TYPE_BUS is what you need to enable the audio routes to use the I2S bus instead of the built-in audio jack.
However, that is likely not the whole story. The DAC likely requires additional configuration commands and/or external triggers. Looking at a similar HAT with the same DAC, for example, there is an I2C bus connection as well for DAC setup commands. Our Assistant sample uses the VoiceHAT driver to accomplish the additional triggering required by the DAC on that peripheral.
In Raspbian, the driver you enable via dtoverlay likely takes care of both pieces. Here, your code will need to manage the setup bits manually. Look at how the VoiceHAT driver is used in the Assistant sample as an example of this.
Also, make sure you are not enabling any of the I2S pins as either GPIO or PWM, as this will disable the audio route per the documentation.
Side Note: Android Things does not support making kernel changes via config.txt, so adding drivers there is expected not to have any effect.
It's been awhile since I figured this out, so I'm posting the code that working for me so that others spend less time buried in manuals.
After I've spent a few hours reading through the manual and frowning on the board's schematic, I figured out that the PCM5122 chip needs some preconfiguration.
It turns out that this chip has a complex clocking scheme. From the datasheet:
The serial audio interface typically has 4 connections: SCK (system master clock), BCK (bit clock), LRCK (left
right word clock), and DIN (data). The device has an internal PLL that is used to take either SCK or BCK and
create the higher rate clocks required by the interpolating processor and the DAC clock. This allows the device to
operate with or without an external SCK.
So, long story short, the chip's PLL operation depends on what pin is physically wired to the Raspberry board - SCK, BCK or both:
In my case it was BCK. We need to select PLL clock source with 13th register:
With all that explained, I'll post the full driver I've used with some additional configuration. All the information you can find in the linked manual. Hope it helps.
class SuptronicsX920AudioDevice private constructor(
private val busDevice: AudioDeviceInfo,
private val i2cDevice: I2cDevice) : AudioDevice {
private var audioTrack: AudioTrack? = null
private var leftVolume = 1f
private var rightVolume = 1f
companion object {
private const val ERROR_DETECT_REG = 37
private const val ERROR_DETECT_IDCM_BIT = 3
private const val PLL_SOURCE_REG = 13
private const val PLL_SOURCE_BCK_BIT = 4
private const val AUTO_MUTE_REG = 65
private const val DIGITAL_VOLUME_LEFT_REG = 61
private const val DIGITAL_VOLUME_RIGHT_REG = 62
fun create(busDevice: AudioDeviceInfo, i2cDevice: I2cDevice): Either<IOException, SuptronicsX920AudioDevice> {
return try {
// Ignore BCK\SCK missing errors as they turn device into Power down mode
riseRegBit(i2cDevice, ERROR_DETECT_REG, ERROR_DETECT_IDCM_BIT)
// Select BCK as the source for PLL
riseRegBit(i2cDevice, PLL_SOURCE_REG, PLL_SOURCE_BCK_BIT)
// Disable auto mute for both channels
i2cDevice.writeRegByte(AUTO_MUTE_REG, 0)
// Set the maximum gain for both channels
i2cDevice.writeRegByte(DIGITAL_VOLUME_LEFT_REG, 0)
i2cDevice.writeRegByte(DIGITAL_VOLUME_RIGHT_REG, 0)
SuptronicsX920AudioDevice(busDevice, i2cDevice).right()
} catch (ioe: IOException) {
e(ioe) { "Unable to configure PCM512x for Suptronics x920" }
ioe.left()
}
}
private fun riseRegBit(i2cDevice: I2cDevice, regAddress: Int, bitAddress: Int) {
val value = i2cDevice.readRegByte(regAddress)
i2cDevice.writeRegByte(regAddress, value or (1 shl bitAddress).toByte())
}
}
override fun play(stream: InputStream, audioFormat: AudioFormat) {
val audioOutputBufferSize = AudioTrack.getMinBufferSize(
audioFormat.sampleRate,
audioFormat.channelMask,
audioFormat.encoding)
val buffer = ByteArray(audioOutputBufferSize)
audioTrack = AudioTrack.Builder()
.setAudioFormat(audioFormat)
.setBufferSizeInBytes(audioOutputBufferSize)
.setTransferMode(AudioTrack.MODE_STREAM)
.build()
audioTrack?.apply {
preferredDevice = busDevice
setStereoVolume(leftVolume, rightVolume)
play()
var bytes = 0
try {
while (stream.read(buffer) > 0) {
bytes += write(buffer, 0, buffer.size, AudioTrack.WRITE_BLOCKING)
}
} catch (error: Throwable) {
e(error) { "Error playing audio" }
}
d { "$bytes of audio track written" }
}
stop()
audioTrack = null
}
override fun stop() {
audioTrack?.apply {
if (state != AudioTrack.STATE_UNINITIALIZED) {
try {
pause()
flush()
release()
d { "Audio stopped" }
} catch (error: Throwable) {
e(error) { "Can't stop track properly" }
}
}
}
}
override fun setVolume(leftVolume: Float, rightVolume: Float) {
this.leftVolume = leftVolume
this.rightVolume = rightVolume
audioTrack?.apply { setStereoVolume(leftVolume, rightVolume) }
}
override fun close() {
stop()
i2cDevice.close()
}
}
I have some trouble to receive data over the USART. What I actually want to achieve ist, that I can receive a command over USART with no specific length (only a maximum possible length). So I use the interrupt routine to check each character received, but I somehow still cannot achieve what I want. The routine is called each time I receive a new character, but somehow HAL_UART_Receive_IT(&huart1,rx_data,buff_size_rx) does not upgrade in realtime, then I don't see the received character when I check rx_data[pointer], but a few time later it is in the rx_data buffer.
What I have so far:
int pointer =0;
...
void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 */
if ( USART1->ISR & UART_IT_TXE) {
}
if ( USART1->ISR & UART_IT_RXNE) {
HAL_UART_Receive_IT(&huart1,rx_data,buff_size_rx);
if(rx_data[pointer]=='\0') {
pointer=0;
readCommand(rx_data);
clearBuffer(rx_data,buff_size_rx);
} else {
pointer++;
if(pointer>=buff_size_rx) {
pointer=0;
}
}
}
/* USER CODE END USART1_IRQn 0 */
HAL_UART_IRQHandler(&huart1);
/* USER CODE BEGIN USART1_IRQn 1 */
/* USER CODE END USART1_IRQn 1 */
}
HAL_UART_Receive_IT() is not meant to be called from an interrupt handler that way, but to initiate receiving a fixed number of bytes via interrupt.
A possible workaround is to check your input buffer after HAL_UART_IRQHandler() completes, i.e. in the /* USER CODE BEGIN USART1_IRQn 1 */ section. When a command is processed, you can reset pRxBuffPtr and RxXferCount in the handle structure to their original values to start from the start of the buffer again.
Another horrible possible workaround would be to call HAL_UART_Receive_IT() with a buffer size of 1, and set up a HAL_UART_RxCpltCallback() handler that checks the received byte each time, and calls HAL_UART_Receive_IT() again when necessary.
Of course you could do it without HAL, as PeterJ and others (always) suggest.
You've already implemented pin and interrupt setup, leave them unchanged at first.
Calculate the UART->BRR value according to the reference manual, or copy the relevant code from hal.
set UART->CR1=USART_CR1_RE|USART_CR1_TE|USART_CR1_UE|USART_CR1_RXNEIE; Now, you are getting interrupts.
In the interrupt function, read UART->SR into a temporary variable, and examine it.
Read UART->DR when there is a received byte waiting, do the error handling otherwise (later).
Get rid of the rest of the HAL calls when the above is working.
Interrupt response and processing time is often critical in embedded applications, and the HAL just wastes a lot of that.
The normal HAL library is not useful for continuous reception or commands with different length.
If you have the complete HAL package installed, you could look at the examples for the LowLevel interface.
Projects\STM32F411RE-Nucleo\Examples_LL\USART\USART_Communication_Rx_IT_Continuous
The main thing is to set you usart to continuous reception:
void Configure_USART(void) {
/* (1) Enable GPIO clock and configures the USART pins *********************/
/* Enable the peripheral clock of GPIO Port */
USARTx_GPIO_CLK_ENABLE();
/* Configure Tx Pin as : Alternate function, High Speed, Push pull, Pull up */
LL_GPIO_SetPinMode(USARTx_TX_GPIO_PORT, USARTx_TX_PIN, LL_GPIO_MODE_ALTERNATE);
USARTx_SET_TX_GPIO_AF();
LL_GPIO_SetPinSpeed(USARTx_TX_GPIO_PORT, USARTx_TX_PIN, LL_GPIO_SPEED_FREQ_HIGH);
LL_GPIO_SetPinOutputType(USARTx_TX_GPIO_PORT, USARTx_TX_PIN, LL_GPIO_OUTPUT_PUSHPULL);
LL_GPIO_SetPinPull(USARTx_TX_GPIO_PORT, USARTx_TX_PIN, LL_GPIO_PULL_UP);
/* Configure Rx Pin as : Alternate function, High Speed, Push pull, Pull up */
LL_GPIO_SetPinMode(USARTx_RX_GPIO_PORT, USARTx_RX_PIN, LL_GPIO_MODE_ALTERNATE);
USARTx_SET_RX_GPIO_AF();
LL_GPIO_SetPinSpeed(USARTx_RX_GPIO_PORT, USARTx_RX_PIN, LL_GPIO_SPEED_FREQ_HIGH);
LL_GPIO_SetPinOutputType(USARTx_RX_GPIO_PORT, USARTx_RX_PIN, LL_GPIO_OUTPUT_PUSHPULL);
LL_GPIO_SetPinPull(USARTx_RX_GPIO_PORT, USARTx_RX_PIN, LL_GPIO_PULL_UP);
/* (2) NVIC Configuration for USART interrupts */
/* - Set priority for USARTx_IRQn */
/* - Enable USARTx_IRQn */
NVIC_SetPriority(USARTx_IRQn, 0);
NVIC_EnableIRQ(USARTx_IRQn);
/* (3) Enable USART peripheral clock and clock source ***********************/
USARTx_CLK_ENABLE();
/* (4) Configure USART functional parameters ********************************/
/* TX/RX direction */
LL_USART_SetTransferDirection(USARTx_INSTANCE, LL_USART_DIRECTION_TX_RX);
/* 8 data bit, 1 start bit, 1 stop bit, no parity */
LL_USART_ConfigCharacter(USARTx_INSTANCE, LL_USART_DATAWIDTH_8B, LL_USART_PARITY_NONE, LL_USART_STOPBITS_1);
/* No Hardware Flow control */
/* Reset value is LL_USART_HWCONTROL_NONE */
// LL_USART_SetHWFlowCtrl(USARTx_INSTANCE, LL_USART_HWCONTROL_NONE);
/* Oversampling by 16 */
/* Reset value is LL_USART_OVERSAMPLING_16 */
// LL_USART_SetOverSampling(USARTx_INSTANCE, LL_USART_OVERSAMPLING_16);
/* Set Baudrate to 115200 using APB frequency set to 100000000/APB_Div Hz */
/* Frequency available for USART peripheral can also be calculated through LL RCC macro */
/* Ex :
Periphclk = LL_RCC_GetUSARTClockFreq(Instance); or
LL_RCC_GetUARTClockFreq(Instance); depending on USART/UART instance
In this example, Peripheral Clock is expected to be equal to
100000000/APB_Div Hz => equal to SystemCoreClock/APB_Div
*/
LL_USART_SetBaudRate(USARTx_INSTANCE, SystemCoreClock/APB_Div, LL_USART_OVERSAMPLING_16, 115200);
/* (5) Enable USART *********************************************************/
LL_USART_Enable(USARTx_INSTANCE);
}
The USART IT Handler should look like
void USARTx_IRQHandler(void)
{
/* Check RXNE flag value in SR register */
if(LL_USART_IsActiveFlag_RXNE(USARTx_INSTANCE) && LL_USART_IsEnabledIT_RXNE(USARTx_INSTANCE))
{
/* RXNE flag will be cleared by reading of DR register (done in call) */
/* Call function in charge of handling Character reception */
USART_CharReception_Callback();
}
else
{
/* Call Error function */
Error_Callback();
}
}
The last thing to set up is the Callback
void USART_CharReception_Callback(void);
Where you could put the bytes into an buffer and handle it in the main loop or where you want.
Since I stumbled over the problem today and could not find a good solution to it, I like to present a very simple one, using most of the HAL but avoiding the problems described...
Short verison of my approach is:
In the last user code section (for the appropriate USART instance, if using more than one) of void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle), enable the IRQ with:
__HAL_UART_ENABLE_IT(&huartx, UART_IT_RXNE);
Then put the desired code in your interrupt function:
void USART3_IRQHandler(void) {
/* USER CODE BEGIN USART3_IRQn 0 */
CallMyCodeHere();
return; // To avoid calling the default HAL handler at all
// (in case you want to save the time)
/* USER CODE END USART3_IRQn 0 */
HAL_UART_IRQHandler(&huart3); // This is the CubeMX generated HAL handler
/* USER CODE BEGIN USART3_IRQn 1 */
/* USER CODE END USART3_IRQn 1 */
}
Don't use HAL_UART_Receive_IT anywhere, it will disable the IRQ and you need to re-enable it, if you want to get called with every reception.
The long version could be found in my post here...
Here is the full example of receiving data and idle line detection by interrupts:
Enable the receive interrupts and idle line detection in main.c:
/* USER CODE BEGIN USART2_Init 2 */
__HAL_UART_ENABLE_IT(&huart2, UART_IT_RXNE); // enable receive intterupts
__HAL_UART_ENABLE_IT(&huart2, UART_IT_IDLE); // enable idle line detection
/* USER CODE END USART2_Init 2 */
Sort out the idle line event from within USARTx_IRQHandler in stm32f4xx_it.c:
void USART2_IRQHandler(void)
{
/* USER CODE BEGIN USART2_IRQn 0 */
if (__HAL_UART_GET_FLAG(&huart2, UART_FLAG_IDLE)) {
__HAL_UART_CLEAR_IDLEFLAG(&huart2); // taken from https://electronics.stackexchange.com/questions/471272/setting-up-stm32-timer-for-uart-idle-detection#comment1353999_480556
uart2_idleHandler();
} else {
uart2_handler();
}
return;
/* USER CODE END USART2_IRQn 0 */
HAL_UART_IRQHandler(&huart2);
/* USER CODE BEGIN USART2_IRQn 1 */
/* USER CODE END USART2_IRQn 1 */
}
Testing:
Create the following handlers:
char my_uart_buffer[256];
int my_uart_buffer_index = 0;
void uart2_handler(void){
char buff;
HAL_UART_Receive (&huart2, (uint8_t *)&buff, 1, 400);
my_uart_buffer[my_uart_buffer_index++] = buff;
}
void uart2_idleHandler(){
my_uart_buffer_index = 0;
}
Open a serial port client in your PC, setup as 115200 baud, 8N1.
Set a breakpoint to uart2_idleHandler().
Send "Hello world".
You can examine your buffer by p/c *my_uart_buffer#20 when breakpoint hits.
Example Project
Here is the full example that runs on STM32F407 Discovery board.
You can make it work using HAL! It may not be as elegant as other implementations but it is doable.
You have to create an error handler function and then the function that calls the HAL_UART_RCV_IT must flush the UART RX whenever there is an overrun error.
In addition, I work with two buffers. While the Interrupt is filling one buffer the main loop is emptying the other.
Here it how it is working well for me:
typedef enum
{
UARTREADY = 0,
UARTBUSY = 1,
UARTDATA = 2,
UARTERROR = 3
} enumUartStatus;
while(1){
if(UARTREADY == isUsart3RxReady()){
Usart3RxBuffer((char *)&SOMRxBytesBuffer[use_buffer_index], RCV_BUFFER_BANK_SIZE); // receive bytes in the raw buffer
if(use_buffer_index == RCV_BUFFER_BANK1_INDEX){
use_buffer_index = RCV_BUFFER_BANK2_INDEX;
rxb1_stats++;
}else{
use_buffer_index = RCV_BUFFER_BANK1_INDEX;
rxb2_stats++;
}
}
}
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
if(huart == NULL){
return;
}
if(huart->Instance == USART3){
if(HAL_UART_GetError(huart) == HAL_UART_ERROR_FE){
Usart3Ready = UARTREADY;
}else{
Usart3Ready = UARTERROR;
}
}
}
void Usart3RxBuffer(char *buffer, unsigned short rxbuffersize){
/* Reset transmission flag */
if(Usart3Ready != UARTREADY)
{
return;
}
if(HAL_UART_GetState(&huart3) == HAL_UART_STATE_READY){
/*##-3- Put UART peripheral in reception process ###########################*/
if (HAL_UART_Receive_IT(&huart3, (uint8_t *)buffer, rxbuffersize) != HAL_OK)
{
// TODO: Error_Handler();
DEBUG_TRACE(DEBUG_MSK_MAIN, "UART3 error starting receiver!\r\n");
}else{
// An interrupt HAL_UART_ErrorCallback hit right here !!!!
// There is an overrun error happening here so we have to retry
// this is because we are using the Receive_IT in a continous communication and there is no handshake or flow control
if(Usart3Ready != UARTERROR){
/* Busy waiting to receive bytes */
Usart3Ready = UARTBUSY;
}
}
}
if(Usart3Ready == UARTERROR){
HAL_UART_AbortReceive_IT(&huart3);
Usart3Ready = UARTREADY;
}
}
I am attempting to send data from device to host using the Gazelle protocol, however, when reading a time varying signal in on MATLAB the values continuously change elements in the array.
Here is the Simblee/Rfduino host code:
#include <SimbleeGZLL.h>
device_t role = HOST;
char array[5];
void setup() {
Serial.begin(9600);
SimbleeGZLL.begin(role);
timer_one(1); // 1 ms timer
}
void loop() {
Serial.flush();
printf(EMG);
}
void SimbleeGZLL_onReceive(device_t device, int rssi, char *data, int len)
{
if (len > 0) {
digitalWrite(2,HIGH);
array[0] = data[0];
array[1] = data[1];
array[2] = data[2];
array[3] = data[3];
array[4] = '\0';
} else SimbleeGZLL.sendToDevice(device, 'A');
}
And the device code:
include
device_t role = DEVICE1;
volatile int state;
char array[4];
void setup() {
SimbleeGZLL.begin(role);
Serial.begin(9600);
timer_one(1);
}
void loop() {
array[0] = analogRead(2);
array[1] = analogRead(3);
array[2] = analogRead(4);
array[3] = analogRead(5);
SimbleeGZLL.sendToHost(EMG,4);
}
Could someone please provide some assistance to identify where the issue may lie?
Thank you!
Matlab is not super reliable with serial communication. I actually had a similar issue with a serial device where the input values would be out of order. Are you signaling when to start and stop printing? What does your matlab code look like?
I would set up a ring buffer on the host and the device to deal with the asycn time issues.
You are going to get timing issues with the current method. What kind of frequency are you going for? The analogRead is super slow, and double multiple in a row seems to make things even slower. Could you try to set up an ADC interrupt?
Where is your timer code?
I am trying to communicate over I2C with a Pololu MinIMU9v2 from a TM4C123GXL Launchpad, but every time I try to write to the bus, I am getting I2C_MASTER_ERR_ADDR_ACK and I2C_MASTER_ERR_DATA_ACK. Printing out the slave address shows that it looks right, so I'm thinking this may be something I may be doing wrong with the use of the TI Launchpad driver library.
Here's the initialization routine:
void
InitI2CBus(void)
{
// Initialize the TM4C I2C hardware for I2C0
SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |
SYSCTL_XTAL_16MHZ);
SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
GPIOPinConfigure(GPIO_PB2_I2C0SCL);
GPIOPinConfigure(GPIO_PB3_I2C0SDA);
GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_3);
// Initialize the bus
I2CMasterInitExpClk(I2C0_BASE, SysCtlClockGet(), false);
}
Here is the code that attempts to read a byte from the device:
uint8_t
ReadByte(uint8_t slaveAddr, uint8_t subAddr)
{
// Write SUB
slaveAddr |= 1; // Set LSB to writemode
I2CMasterSlaveAddrSet(I2C0_BASE, slaveAddr, false);
I2CMasterDataPut(I2C0_BASE, subAddr);
I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_SEND);
while(I2CMasterBusy(I2C0_BASE)) { }
if (CheckError())
{
return 0;
}
// Read data
slaveAddr &= ~1; // Set LSB to readmode
I2CMasterSlaveAddrSet(I2C0_BASE, slaveAddr, true);
I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE);
while(I2CMasterBusy(I2C0_BASE)) { }
I2CMasterControl(I2C0_BASE, I2C_MASTER_CMD_SINGLE_RECEIVE);
while(I2CMasterBusy(I2C0_BASE)) { }
uint8_t response = I2CMasterDataGet(I2C0_BASE);
if (CheckError())
{
return 0;
}
return response;
}
Any ideas what I may be doing wrong?
I was having a heck of a time getting my I2C bus working on this board. I'm not sure if this is your issue, but here's the initialization code I'm using (I'm on I2C2):
1. SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C2);
2. SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
**3. GPIOPinTypeI2CSCL(GPIO_PORTF_BASE, GPIO_PIN_6);**
4. GPIOPinTypeI2C(GPIO_PORTF_BASE, GPIO_PIN_7);
5. GPIOPinConfigure(GPIO_PF6_I2C2SCL);
6. GPIOPinConfigure(GPIO_PF7_I2C2SDA);
7. I2CMasterInitExpClk(I2C2_BASE, SysCtlClockGet(), false);
8. I2CMasterSlaveAddrSet(I2C2_BASE, 0x48, false);
Line 3 was missing from most of the examples I could find, and I noticed it's also missing from your code. Before I added this line, I couldn't get my I2C bus to do anything; after adding it it's at least transferring data.
I'm not sure if this is the source of your issue or not, but thought I'd pass it along in case it helps.