Related
I'm getting FIFO data from MAX30100 using the MCU STM32F4 to measure Heart Rate. In the signal received I can see the Heart Beat but also fails in the samples, as u can see below:
I'm dont have a filter working but the signal without filter was diferent when I did this on the Arduino board. Am I losting samples or it's normal? What I did wrong?
Datasheet MAX30100: https://img.filipeflop.com/files/download/Datasheet_MAX30100.pdf
Following my code:
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "usb_device.h"
/* Private define ------------------------------------------------------------*/
// FIFO registers
#define MAX30100_FIFO_W_POINTER 0x02
#define MAX30100_OVF_COUNTER 0x03
#define MAX30100_FIFO_R_POINTER 0x04
#define MAX30100_FIFO_DATA_REG 0x05
// configuration registers
#define MAX30100_MODE_CONFIG 0x06
#define MAX30100_SPO2_CONFIG 0x07
#define MAX30100_LED_CONFIG 0x09
// PART ID registers
#define MAX30100_PART_ID 0xFF
// MAX30100 I2C addresses
#define MAX30100_WADDRESS 0xAE // 8bit address converted to 7bit + W
#define MAX30100_RADDRESS 0xAF // 8bit address converted to 7bit + R
/* Private variables ---------------------------------------------------------*/
I2C_HandleTypeDef hi2c3;
char buffer[30];
unsigned long ir_buff[16] = {0}, red_buff[16] = {0};
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_I2C3_Init(void);
uint8_t CDC_Transmit_FS(char* Buf, uint16_t Len);
uint8_t MAX30100_getNumSamp(uint16_t* ir_buff, uint16_t* red_buff);
uint8_t MAX30100_getPartID(void);
void MAX30100_reset(void);
void MAX30100_wakeup(void);
void MAX30100_SetHR (void);
void MAX30100_InitFIFO (void);
void MAX30100_setLEDs(uint8_t ledCurrentRed, uint8_t ledCurrentIr);
void MAX30100_setSR(uint8_t sr);
void MAX30100_setPW (uint8_t pw);
uint8_t MAX30100_read (uint8_t device_register);
void MAX30100_write (uint8_t device_register, uint8_t reg_data);
int main(void)
{
uint8_t id;
uint8_t i;
uint8_t samples;
uint16_t ir_average = 0;
uint16_t red_average = 0;
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_I2C3_Init();
MX_USB_DEVICE_Init();
HAL_Delay(10);
MAX30100_reset();
id = MAX30100_getPartID();
if (id == 0x11) //OK
// Set LED current
MAX30100_setLEDs(0x07, 0xFF);
// Set sample rate
MAX30100_setSR(0x00);
// Set pulse width
MAX30100_setPW(0x3);
// Set heart rate mode
MAX30100_SetHR ();
// Set RD and WR pointers to 0x00
MAX30100_InitFIFO();
// Wake up
MAX30100_wakeup();
while (1)
{
// Gets the number of samples in the FIFO and reads then
samples = MAX30100_getNumSamp((uint16_t*)ir_buff, (uint16_t*)red_buff);
if (samples > 0 )
{
// we have data in FIFO
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_14,1); //LED ON
ir_average = 0;
red_average = 0;
for (i = 0; i < samples; i++)
{
ir_average += (uint16_t)ir_buff[i];
red_average += (uint16_t)red_buff[i];
}
ir_average /= samples; // calculate the average value for this reading
red_average /= samples;
memset(buffer,0,sizeof(buffer));
sprintf(buffer, "HR: %d,", (uint16_t)ir_average);
CDC_Transmit_FS((char*)buffer, 20); //print the ir value to CDC
}
else
{
// There's no data in FIFO
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_14,0); //LED OFF
HAL_Delay(1); // Wait for samples to be aquired
}
}
}
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 25;
RCC_OscInitStruct.PLL.PLLN = 336;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV4;
RCC_OscInitStruct.PLL.PLLQ = 7;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV2;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
{
Error_Handler();
}
}
static void MX_I2C3_Init(void)
{
hi2c3.Instance = I2C3;
hi2c3.Init.ClockSpeed = 400000;
hi2c3.Init.DutyCycle = I2C_DUTYCYCLE_2;
hi2c3.Init.OwnAddress1 = 0;
hi2c3.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c3.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c3.Init.OwnAddress2 = 0;
hi2c3.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c3.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if (HAL_I2C_Init(&hi2c3) != HAL_OK)
{
Error_Handler();
}
}
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOH_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_14|GPIO_PIN_15, GPIO_PIN_RESET);
/*Configure GPIO pins : PC14 PC15 */
GPIO_InitStruct.Pin = GPIO_PIN_14|GPIO_PIN_15;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
}
// Reads from register 0xFF
// should return 0x11
uint8_t MAX30100_getPartID(void)
{
uint8_t reg;
reg = MAX30100_read (MAX30100_PART_ID);
return reg;
}
// Resets the MAX30100 IC
void MAX30100_reset(void)
{
uint8_t reg;
reg = MAX30100_read (MAX30100_MODE_CONFIG);
// RESET bit is B6
// 0x40 = 0100 0000
reg = (reg | 0x40); // Set reset bit to 1
MAX30100_write (MAX30100_MODE_CONFIG, reg);
}
// Wakes up the MAX30100
void MAX30100_wakeup(void)
{
uint8_t reg;
reg = MAX30100_read (MAX30100_MODE_CONFIG);
reg = reg & 0x7F; // Set SHDN bit to 0
MAX30100_write (MAX30100_MODE_CONFIG, reg);
}
// Sets Heart rate mode
// This means MODE{2:0} = 0b010 (or 0x02 in hexadecimal)
void MAX30100_SetHR (void)
{
uint8_t reg;
reg = MAX30100_read (MAX30100_MODE_CONFIG);
// RESET bit is B7
// First we clear bits 2:0
reg = reg & 0xF8;
// Then we set bits 2:0 to 0x02
reg = reg | 0x02;
MAX30100_write (MAX30100_MODE_CONFIG, reg);
}
// Initializes FIFO
// Sets RD and WR pointers to 0
// Clears OVF
void MAX30100_InitFIFO (void)
{
MAX30100_write (MAX30100_FIFO_W_POINTER, 0x00);
MAX30100_write (MAX30100_FIFO_R_POINTER, 0x00);
MAX30100_write (MAX30100_OVF_COUNTER, 0x00);
}
// Sets LED currents
void MAX30100_setLEDs(uint8_t ledCurrentRed, uint8_t ledCurrentIr)
{
uint8_t reg;
reg = ( ledCurrentRed << 4 ) | ledCurrentIr;
MAX30100_write (MAX30100_LED_CONFIG, reg);
}
// Sets sample rate
// sample rate is bits 4:2 of register MAX30100_SPO2_CONFIG
// bitmask is 0xE3
void MAX30100_setSR (uint8_t sr)
{
uint8_t reg;
reg = MAX30100_read (MAX30100_SPO2_CONFIG);
reg = reg & 0xE3;
reg = reg | (sr << 2);
MAX30100_write (MAX30100_SPO2_CONFIG, reg);
}
// Sets pulse width
// sample rate is bits 1:0 of register MAX30100_SPO2_CONFIG
void MAX30100_setPW (uint8_t pw)
{
uint8_t reg;
reg = MAX30100_read (MAX30100_SPO2_CONFIG);
reg = reg & 0xFC;
reg = reg | pw;
MAX30100_write (MAX30100_SPO2_CONFIG, reg);
}
// Gets number of samples in FIFO and read then
uint8_t MAX30100_getNumSamp(uint16_t* ir_buff, uint16_t* red_buff)
{
uint8_t wreg;
uint8_t rreg;
uint8_t sampleNum;
uint8_t samples[4];
wreg = MAX30100_read (MAX30100_FIFO_W_POINTER);
rreg = MAX30100_read (MAX30100_FIFO_R_POINTER);
sampleNum = (abs( 16 + wreg - rreg ) % 16);
if(sampleNum > 0)
{
//HAL_I2C_Mem_Read(&hi2c3,MAX30100_RADDRESS,MAX30100_FIFO_DATA_REG,4,(uint8_t*)samples,1,1000);
HAL_I2C_Mem_Read(&hi2c3,MAX30100_RADDRESS,MAX30100_FIFO_DATA_REG,1,&samples[0],1,250);
HAL_I2C_Mem_Read(&hi2c3,MAX30100_RADDRESS,MAX30100_FIFO_DATA_REG,1,&samples[1],1,250);
HAL_I2C_Mem_Read(&hi2c3,MAX30100_RADDRESS,MAX30100_FIFO_DATA_REG,1,&samples[2],1,250);
HAL_I2C_Mem_Read(&hi2c3,MAX30100_RADDRESS,MAX30100_FIFO_DATA_REG,1,&samples[3],1,250);
*(ir_buff) = (uint16_t)samples[1];
*(ir_buff++) |= (uint16_t)samples[0] << 8;
*(red_buff) = (uint16_t)samples[3];
*(red_buff++) |= (uint16_t) samples[2] << 8;
//HAL_Delay(7); // just test
}
return sampleNum;
}
// My I2C read and write functions
uint8_t MAX30100_read (uint8_t device_register )
{
uint8_t read_data;
HAL_I2C_Mem_Read(&hi2c3,MAX30100_RADDRESS,device_register,I2C_MEMADD_SIZE_8BIT,&read_data,1,250);
return read_data;
}
void MAX30100_write (uint8_t device_register, uint8_t reg_data)
{
HAL_I2C_Mem_Write(&hi2c3,MAX30100_WADDRESS,device_register,I2C_MEMADD_SIZE_8BIT,®_data,1,250);
}
i want to read touch activity from the touchscreen.If i touch, i want to led blink. Some my definitions in below code but generally i want to get my activity with i2c
Some definitions:
uint8_t deviceaddr;
static uint32_t touch_i2c_read(uint8_t DeviceAddr, uint8_t RegAddr, uint8_t *pBuffer, uint16_t len);
static const int I2C_TIMEOUT = 65536;
unsigned char i2c_buffer[256];
uint32_t res;
This is my i2c read code:
static uint32_t touch_i2c_read(uint8_t DeviceAddr, uint8_t RegAddr, uint8_t *pBuffer, uint16_t len)
{ //uint8_t deviceaddr ,0x00,(uint8_t *)&buf, sizeof(buf)
uint32_t timeout = I2C_TIMEOUT;
while (I2C_GetFlagStatus(I2C1, I2C_ISR_BUSY) != RESET)
{
if ((timeout--) == 0)
return 0;
}
I2C_TransferHandling(I2C1, DeviceAddr << 1, 1, I2C_SoftEnd_Mode, I2C_Generate_Start_Write);
/* !!! Wait until TXIS flag is set !!! */
timeout = I2C_TIMEOUT;
while (I2C_GetFlagStatus(I2C1, I2C_ISR_TXIS) == RESET)
{
if ((timeout--) == 0)
return 0;
}
}
This is my settings
void configure_interrupt_pins()
{
GPIO_InitTypeDef GPIO_InitStruct;
EXTI_InitTypeDef EXTI_InitStruct;
NVIC_InitTypeDef NVIC_InitStruct;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStruct);
/*ENABLE CLOCK FOR GPIOX*/
RCC_APB1PeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
// ENABLE CLOCK FOR SYSCFG
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
//SET PIN AS INPUT
// init_pin(EX_NCVIC_PORT, EX_NCVIC_Pin, GPIO_MODE_INPUT, GPIO_Speed_50MHz, GPIO_OType_PP, GPIO_PuPd_UP);
//TELL THE SYSTEM THAT YOU WILL USE PXX FOR EXTI_LineX
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOx, EXTI_PinSourcex);
//CONFIGIRATION of exti
EXTI_InitStruct.EXTI_Line = EXTI_Linex; //pxx connect to line x
EXTI_InitStruct.EXTI_LineCmd = ENABLE; //enable interrupt
EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt; //interrupt mode
EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising_Falling; //triggers on rising and failing edge
EXTI_Init(&EXTI_InitStruct); //add to exti
//CONFIGURATION of nvic
NVIC_InitStruct.NVIC_IRQChannel = EXTI0_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x00;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0x00;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
}
This is my interrupt
void EXTI0_IRQHandler(void)
{
if (EXTI_GetITStatus((EXTI_Line0) != RESET))
{
res = touch_i2c_read(0x42, 0x00, i2c_buffer, 22);
printf("deneme");
if (!res)
{
GPIO_SetBits(GPIOE, GPIO_Pin_13);
}
else
{
GPIO_SetBits(GPIOE, GPIO_Pin_13);
}
EXTI_ClearITPendingBit(EXTI_Line0);
}
}
But my code not working. Stm32 dont understand touch activity how can i solve this.
Edit i change line 1 every external interupts but i have res value 0 how can i fix this it must be different 0
Using a while() loop in an interrupt will cause problems, because the controller will never exit the loop. Try to use your i2c read Function in main() (with other words, a not-interrupt-context) and look if it works there.
I solved this error.
I hadn't any signal pb7 and pb6 so i changed codes as below:
// enable APB1 peripheral clock for I2C1
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
// enable clock for SCL and SDA pins
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
And then,
Device adress of the FT6236 was mising. it is not include at datasheet so i used debugging. I found the device adress which is the (0x32). And than my code working succesfully.
I am trying to use the STM32F4 discovery board as a master to communicate to a sensor using I2C. I am using the std periph library to do this but for some reason I am unable to get anything going through the SCL and SDA lines. From reading through the stf periph header files and other examples I have seen online it does not seem that I am doing anything wrong or forgetting a step. Below I have Included all of my I2C code:
#define I2CTransmitter 0
#define I2CReciever 1
#define I2CAckEnable 1
#define I2CAckDisable 0
void I2CInit() {
I2C_InitTypeDef I2CInitStruct;
GPIO_InitTypeDef GPIO;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOB, ENABLE);
//Configure and initialize the GPIOs
GPIO.GPIO_Pin = GPIO_Pin_6;
GPIO.GPIO_Mode = GPIO_Mode_AF;
GPIO.GPIO_Speed = GPIO_Speed_100MHz;
GPIO.GPIO_OType = GPIO_OType_OD;
GPIO.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOB, &GPIO);
GPIO.GPIO_Pin = GPIO_Pin_7;
GPIO_Init(GPIOB, &GPIO);
//Connect GPIO pins to peripheral
GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_I2C1);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_I2C1);
I2CInitStruct.I2C_ClockSpeed = 100000;
I2CInitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2CInitStruct.I2C_Mode = I2C_Mode_I2C;
I2CInitStruct.I2C_OwnAddress1 = 0x00;
I2CInitStruct.I2C_Ack = I2C_Ack_Enable;
I2CInitStruct.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_Init(I2C1, &I2CInitStruct);
I2C_Cmd(I2C1, ENABLE);
}
uint8_t I2CRead(uint8_t address, uint8_t reg) {
uint8_t data;
I2CStart(address, I2CTransmitter, I2CAckEnable);
I2CWriteData(reg);
I2CStart(address, I2CReciever, I2CAckDisable);
data = I2CReadNAck();
I2CStop();
return data;
}
void I2CWrite(uint8_t address, uint8_t reg, uint8_t data) {
I2CStart(address, I2CTransmitter, I2CAckEnable);
I2CWriteData(reg);
I2CWriteData(data);
I2CStop();
}
void I2CStart(uint8_t address, uint8_t direction, uint8_t ack) {
I2C_GenerateSTART(I2C1, ENABLE);
I2C_Send7bitAddress(I2C1, address, direction);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_SLAVE_BYTE_RECEIVED));
}
void I2CStop() {
I2C_GenerateSTOP(I2C1, ENABLE);
}
void I2CWriteData(uint8_t data) {
I2C_SendData(I2C1, data);
while(!I2C_CheckEvent(I2C1, I2C_EVENT_SLAVE_BYTE_RECEIVED));
}
uint8_t I2CReadAck() {
uint8_t data;
I2C_AcknowledgeConfig(I2C1, ENABLE);
while( !I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED) );
data = I2C_ReceiveData(I2C1);
return data;
}
uint8_t I2CReadNAck() {
uint8_t data;
I2C_AcknowledgeConfig(I2C1, DISABLE);
I2C_GenerateSTOP(I2C1, ENABLE);
while( !I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED) );
data = I2C_ReceiveData(I2C1);
return data;
}
The code is used in the main function by simply calling I2CInit() and then calling I2CWrite() in a while loop for testing. Thank you in advance for any help!
I try to finish the code about: ADC using DMA and then the data transfer through PC by using USART. I want to use USART_DMA to avoid occupying CPU. I use sample frequency rate 1000Hz by using array ADC[] and delay 1ms (delay here mean I use systemtick, you haven't check this point I am sure it work well).
In this code below, have I missed something?
So here my code:
USART_DMA code:
/* USARTx configured as follow:
- BaudRate = 115200 baud
- Word Length = 8 Bits
- One Stop Bit
- No parity
- Hardware flow control disabled (RTS and CTS signals)
- Receive and transmit enabled
*/
#include "USART.h"
char TxBuffer[16];
USART_InitTypeDef USART_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
void USART_Configuration(unsigned int BaudRate)
{
/* Characteristic of USART*/
USART_InitStructure.USART_BaudRate = BaudRate;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART1, &USART_InitStructure);
/* Enable USART*/
USART_Cmd(USART1, ENABLE);
}
void DMA_Configuration(void)
{
DMA_DeInit(DMA1_Channel2);
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)TxBuffer; // send buffer
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART1->DR;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; // Transmit
DMA_InitStructure.DMA_BufferSize = 1;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel2, &DMA_InitStructure);
DMA_Cmd(DMA1_Channel2, ENABLE);
USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);
while (DMA_GetFlagStatus(DMA1_FLAG_TC2) == RESET)
{}
}
ADC_DMA code:
#include "ADC_DMA.h"
uint32_t ADCValue[2] = {0};
void ADC_DMA(void){
ADC_InitTypeDef ADC_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
/* DMA Configure */
DMA_DeInit(DMA1_Channel1);
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADCValue; // address of array data
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&(ADC1->DR));
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = 2; // kich thuoc mang du lieu tuong ung so phan tu cua ADCValue
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
/* DMA1_Stream0 enable */
DMA_Cmd(DMA1_Channel1, ENABLE);
/* ADC Common Init */
ADC_InitStructure.ADC_ScanConvMode = ENABLE;
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel = 2; //so kenh ADC chuyen doi
ADC_Init(ADC1, &ADC_InitStructure);
/* ADC1 regular channels configuration */
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_7Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_7Cycles5);
/* Enable ADC DMA */
ADC_DMACmd(ADC1, ENABLE);
/* Enable ADC1 */
ADC_Cmd(ADC1, ENABLE);
/* Enable ADC1 reset calibration register */
ADC_ResetCalibration(ADC1);
/* Check the end of ADC1 reset calibration register */
while(ADC_GetResetCalibrationStatus(ADC1));
/* Start ADC1 calibration */
ADC_StartCalibration(ADC1);
/* Check the end of ADC1 calibration */
while(ADC_GetCalibrationStatus(ADC1));
/* Start ADC1 Software Conversion */
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
}
Main function:
#include "stm32f10x.h"
#include "stdio.h"
#include "ADC_DMA.h"
#include "USART.h"
/* Declare variable*/
__IO uint16_t x,y;
extern uint32_t time=0;
extern uint32_t ADCValue[];
extern char TxBuffer[16];
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
void GPIO_Configuration(void);
void Delay(__IO uint32_t nCount);
int main()
{
GPIO_Configuration();
ADC_DMA();
RCC_DeInit();
USART_Configuration(115200);
SysTick_Config(SystemCoreClock / 1000);
/****************************************
*SystemFrequency/1000 1ms *
*SystemFrequency/100000 10us *
*SystemFrequency/1000000 1us *
*****************************************/
while(1)
{
Delay(1000); // 100000 = 100ms
x = ADCValue[0];
y = ADCValue[1];
}
sprintf(TxBuffer,"%d#\n%d$\n", x,y);
}
}
void GPIO_Configuration(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOB, ENABLE);
/* Configure PB0 PB1 in output pushpull mode */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* Configure PA0 in input mode */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Enable clock DMA1 */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
/* Enable clock ADC1 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA, ENABLE);
/* Configure ADC Pin PA0 & PA1 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Enable clock for USART1*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
/* Enable clock DMA1 */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
/* Configure USART Tx as alternate function */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Configure USART Rx as alternate function */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
void Delay(__IO uint32_t nCount)
{
time = nCount;
while(nCount--);
}
#ifdef USE_FULL_ASSERT
void assert_failed(uint8_t* file, uint32_t line)
{
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* Infinite loop */
while (1)
{
}
}
#endif
How can I use the I2C for read data from the LSM303DLHC(Magnetometer) and store data in memory, in a buffer, via DMA ?
I try to modify the "LSM303DLHC_Read()" function to use it with the DMA but the output on the SerialChart is always 0.
Can you show me an example of I2C with DMA ?
uint16_t LSM303DLHC_DMA_Read(uint8_t DeviceAddr, uint8_t RegisterAddr, uint16_t NumByteToRead)
{
__IO uint32_t LSM303DLHC_Timeout = LSM303DLHC_LONG_TIMEOUT;
__IO uint32_t temp;
I2C_Initialization();
DMA_Config();
restart:
LSM303DLHC_Timeout = LSM303DLHC_LONG_TIMEOUT;
/* Send START condition */
I2C_GenerateSTART(LSM303DLHC_I2C, ENABLE);
/* Test on EV5 and clear it */
while (!I2C_CheckEvent(LSM303DLHC_I2C, I2C_EVENT_MASTER_MODE_SELECT))
{
if (LSM303DLHC_Timeout-- == 0)
return ERROR;
}
/* Active the needed channel Request */
I2C_DMACmd(I2C1, ENABLE);
LSM303DLHC_Timeout = LSM303DLHC_LONG_TIMEOUT;
/* Send slave address for read */
I2C_Send7bitAddress(LSM303DLHC_I2C, DeviceAddr, I2C_Direction_Transmitter);
while (!I2C_CheckEvent(LSM303DLHC_I2C,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
{
if (LSM303DLHC_Timeout-- == 0)
{
I2C_ClearFlag(LSM303DLHC_I2C,I2C_FLAG_BUSY|I2C_FLAG_AF);
goto restart;
}
}
/* Clear EV6 by setting again the PE bit */
I2C_Cmd(LSM303DLHC_I2C, ENABLE);
I2C_SendData(LSM303DLHC_I2C, RegisterAddr);
/* Test on EV8 and clear it */
LSM303DLHC_Timeout = LSM303DLHC_LONG_TIMEOUT;
while (!I2C_CheckEvent(LSM303DLHC_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
{
if (LSM303DLHC_Timeout-- == 0)
return ERROR;
}
if (NumByteToRead == 0x01)
{
restart3:
/* Send START condition */
I2C_GenerateSTART(LSM303DLHC_I2C, ENABLE);
while (!I2C_CheckEvent(LSM303DLHC_I2C, I2C_EVENT_MASTER_MODE_SELECT));
/* Send Slave address for read */
I2C_Send7bitAddress(LSM303DLHC_I2C, DeviceAddr, I2C_Direction_Receiver);
/* Wait until ADDR is set */
LSM303DLHC_Timeout = LSM303DLHC_LONG_TIMEOUT;
while (!I2C_GetFlagStatus(LSM303DLHC_I2C, I2C_FLAG_ADDR))
{
if (LSM303DLHC_Timeout-- == 0)
{
I2C_ClearFlag(LSM303DLHC_I2C,I2C_FLAG_BUSY|I2C_FLAG_AF);
goto restart3;
}
}
/* Clear ACK */
I2C_AcknowledgeConfig(LSM303DLHC_I2C, DISABLE);
I2C_NACKPositionConfig(LSM303DLHC_I2C, I2C_NACKPosition_Current);
__disable_irq();
/* Clear ADDR flag */
temp = LSM303DLHC_I2C->SR2;
/* Program the STOP */
I2C_GenerateSTOP(LSM303DLHC_I2C, ENABLE);
__enable_irq();
while ((I2C_GetLastEvent(LSM303DLHC_I2C) & 0x0040) != 0x000040); /* Poll on RxNE */
I2C_DMACmd(I2C1, DISABLE);
/* Read the data */
//*pBuffer = I2C_ReceiveData(LSM303DLHC_I2C);
/* Make sure that the STOP bit is cleared by Hardware before CR1 write access */
while ((LSM303DLHC_I2C->CR1&0x200) == 0x200);
/* Enable Acknowledgement to be ready for another reception */
I2C_AcknowledgeConfig(LSM303DLHC_I2C, ENABLE);
return SUCCESS;
}
}
This is the DMA configuration :
void DMA_Config(void)
{
DMA_InitTypeDef DMA_InitStructure;
/* Enable DMA clock */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
/* Reset DMA Stream registers (for debug purpose) */
DMA_DeInit(DMA1_Stream0);
/* Check if the DMA Stream is disabled before enabling it.
Note that this step is useful when the same Stream is used multiple times:
enabled, then disabled then re-enabled... In this case, the DMA Stream disable
will be effective only at the end of the ongoing data transfer and it will
not be possible to re-configure it before making sure that the Enable bit
has been cleared by hardware. If the Stream is used only once, this step might
be bypassed. */
while (DMA_GetCmdStatus(DMA1_Stream0) != DISABLE) {}
/* Configure DMA Stream */
DMA_InitStructure.DMA_Channel = DMA_Channel_1;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)I2C_Register_DR;
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)Buffer_X;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStructure.DMA_BufferSize = 1 ;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA1_Stream0, &DMA_InitStructure);
/* Enable DMA Stream Transfer Complete interrupt */
DMA_ITConfig(DMA1_Stream0, DMA_IT_TC, ENABLE);
/* DMA Stream enable */
DMA_Cmd(DMA1_Stream0, ENABLE);
/* Check if the DMA Stream has been effectively enabled.
The DMA Stream Enable bit is cleared immediately by hardware if there is an
error in the configuration parameters and the transfer is no started (ie. when
wrong FIFO threshold is configured ...) */
// while ((DMA_GetCmdStatus(DMA2_Stream0) != ENABLE))
// { }
}
And this is the I2C configuration :
void I2C_Initialization(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
I2C_InitTypeDef I2C_InitStructure;
/* Enable the I2C periph */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
/* Enable SCK and SDA GPIO clocks */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB , ENABLE);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_I2C1);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_I2C1);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
/* I2C SCK pin configuration */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* I2C SDA pin configuration */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* I2C configuration -------------------------------------------------------*/
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStructure.I2C_OwnAddress1 = 0x00;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStructure.I2C_ClockSpeed = 100000;
/* Apply LSM303DLHC_I2C configuration after enabling it */
I2C_Init(I2C1, &I2C_InitStructure);
/* Active the needed channel Request */
//I2C_DMACmd(I2C1, ENABLE);
/* LSM303DLHC_I2C Peripheral Enable */
I2C_Cmd(I2C1, ENABLE);
}
my first question is why you have DMA config and I2C initialization functions in read function?
I believe you're missing the configuration line for DMA1_Stream6. You'll need to alter the DMA_InitStructure and initialize the Tx stream - right now you're only initializing the Rx Stream. Something like the following should work:
DMA_InitTypeDef DMA_InitStructure;
DMA_DeInit(DMA1_Stream0); //reset DMA1 channe1 to default values;
DMA_InitStructure.DMA_Channel = DMA_Channel_1;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)I2C1_DR_ADDRESS;
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)I2C_RxBuffer;
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
DMA_InitStructure.DMA_BufferSize = 1;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA1_Stream0, &DMA_InitStructure);
DMA_Cmd(DMA1_Stream0, ENABLE);
while (DMA_GetCmdStatus(DMA1_Stream6) != ENABLE);
DMA_ClearFlag(DMA1_Stream0, DMA_FLAG_TCIF0 | DMA_FLAG_FEIF0 | DMA_FLAG_DMEIF0 | \
DMA_FLAG_TEIF0 | DMA_FLAG_HTIF0);
DMA_DeInit(DMA1_Stream6);
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)I2C_TxBuffer;
DMA_InitStructure.DMA_BufferSize = 1;
DMA_Init(DMA1_Stream6, &DMA_InitStructure);
DMA_Cmd(DMA1_Stream6, ENABLE);
while (DMA_GetCmdStatus(DMA1_Stream6) != ENABLE);
DMA_ClearFlag(DMA1_Stream6, DMA_FLAG_TCIF6 | DMA_FLAG_FEIF6 | DMA_FLAG_DMEIF6 | \
DMA_FLAG_TEIF6 | DMA_FLAG_HTIF6);