diff --git a/Makefile b/Makefile index 6e70113ac0619acc80e1990f9ebc4a9718c73085..ffe548d0b9f8e95c3feee3b8a11615f0f06003f1 100755 --- a/Makefile +++ b/Makefile @@ -9,6 +9,7 @@ TARGET_FILES+=src/stm32f4xx_hal_msp.c TARGET_FILES+=src/gpio.c TARGET_FILES+=src/eeprom.c TARGET_FILES+=src/ram.c +TARGET_FILES+=src/adc_dma.c TARGET_FILES+=src/bioloid_time.c TARGET_FILES+=src/bioloid_dyn_slave.c TARGET_FILES+=src/bioloid_dyn_master_sensors.c @@ -70,6 +71,8 @@ TARGET_FILES+=$(HAL_PATH)/src/stm32f4xx_hal_flash_ex.c TARGET_FILES+=$(HAL_PATH)/src/stm32f4xx_hal_dma.c TARGET_FILES+=$(HAL_PATH)/src/stm32f4xx_hal.c TARGET_FILES+=$(HAL_PATH)/src/stm32f4xx_hal_uart.c +TARGET_FILES+=$(HAL_PATH)/src/stm32f4xx_hal_adc.c +TARGET_FILES+=$(HAL_PATH)/src/stm32f4xx_hal_adc_ex.c TARGET_FILES+=$(USART_PATH)/src/usart3.c TARGET_FILES+=$(USART_PATH)/src/usart2.c diff --git a/include/adc_dma.h b/include/adc_dma.h index 05699e454d72613ae80b01356927b9f66267f39d..2999be465858f1d2b489991449107781aa647bd4 100644 --- a/include/adc_dma.h +++ b/include/adc_dma.h @@ -5,10 +5,12 @@ extern "C" { #endif -#include "stm32f4xx.h" +#include "stm32f4xx_hal.h" void adc_init(void); -uint16_t adc_get_temperature(void); +void adc_start(void); +void adc_set_period(uint8_t period_ms); +void adc_stop(void); #ifdef __cplusplus } diff --git a/include/bioloid_registers.h b/include/bioloid_registers.h index c18bb7d75d894c644b1df97e7d1a1b1fe63f8c8d..751a4430e99506b00cb1e2b03617a9cb97d9286e 100644 --- a/include/bioloid_registers.h +++ b/include/bioloid_registers.h @@ -46,6 +46,25 @@ typedef enum { // | | | | interrupt flag | enable interrupt | value | internally used BIOLOID_MODE_PB_CNTRL = 0x2F, // bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 // | | | | interrupt flag | enable interrupt | value | internally used + BIOLOID_ADC_CNTRL = 0x30, // bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 + // | | | | | | | Enable + BIOLOID_ADC_PERIOD = 0x31, + BIOLOID_ADC_CH1_L = 0x32, + BIOLOID_ADC_CH1_H = 0x33, + BIOLOID_ADC_CH2_L = 0x34, + BIOLOID_ADC_CH2_H = 0x35, + BIOLOID_ADC_CH3_L = 0x36, + BIOLOID_ADC_CH3_H = 0x37, + BIOLOID_ADC_CH4_L = 0x38, + BIOLOID_ADC_CH4_H = 0x39, + BIOLOID_ADC_TEMP_L = 0x3A, + BIOLOID_ADC_TEMP_H = 0x3B, + BIOLOID_ADC_CH6_L = 0x3C, + BIOLOID_ADC_CH6_H = 0x3D, + BIOLOID_ADC_VREF_L = 0x3E, + BIOLOID_ADC_VREF_H = 0x3F, + BIOLOID_ADC_CH8_L = 0x40, + BIOLOID_ADC_CH8_H = 0x41 } bioloid_registers; #define GPIO_BASE_ADDRESS 0x20 diff --git a/src/adc_dma.c b/src/adc_dma.c index 19a70aaa2a82ab8a8194a83765c07b2e29f8c6bc..6ee1685d2bea9ff9c1f7c40cc3482a539c98fc87 100644 --- a/src/adc_dma.c +++ b/src/adc_dma.c @@ -1,145 +1,370 @@ #include "adc_dma.h" #include "ram.h" -#define ADC1_CH1 ADC_Channel_TempSensor -#define ADC1_CH2 ADC_Channel_8 -#define ADC1_CH3 ADC_Channel_10 -#define ADC1_CH4 ADC_Channel_12 - -#define ADC2_CH1 ADC_Channel_14 -#define ADC2_CH2 ADC_Channel_9 -#define ADC2_CH3 ADC_Channel_11 -#define ADC2_CH4 ADC_Channel_13 - -#define ADC1_CH2_PIN GPIO_Pin_8 -#define ADC1_CH2_PORT GPIOB -#define ADC1_CH2_PORT_CLK RCC_AHB1Periph_GPIOB -#define ADC1_CH3_PIN GPIO_Pin_0 -#define ADC1_CH3_PORT GPIOC -#define ADC1_CH3_PORT_CLK RCC_AHB1Periph_GPIOC -#define ADC1_CH4_PIN GPIO_Pin_2 -#define ADC1_CH4_PORT GPIOC -#define ADC1_CH4_PORT_CLK RCC_AHB1Periph_GPIOC - -#define ADC2_CH1_PIN GPIO_Pin_4 -#define ADC2_CH1_PORT GPIOC -#define ADC2_CH1_PORT_CLK RCC_AHB1Periph_GPIOC -#define ADC2_CH2_PIN GPIO_Pin_1 -#define ADC2_CH2_PORT GPIOB -#define ADC2_CH2_PORT_CLK RCC_AHB1Periph_GPIOB -#define ADC2_CH3_PIN GPIO_Pin_1 -#define ADC2_CH3_PORT GPIOC -#define ADC2_CH3_PORT_CLK RCC_AHB1Periph_GPIOC -#define ADC2_CH4_PIN GPIO_Pin_3 -#define ADC2_CH4_PORT GPIOC -#define ADC2_CH4_PORT_CLK RCC_AHB1Periph_GPIOC - -#define ADC_CCR_ADDRESS ((uint32_t)0x40012308) +#define ADC1_CH1 ADC_CHANNEL_6 +#define ADC1_CH2 ADC_CHANNEL_8 +#define ADC1_CH3 ADC_CHANNEL_TEMPSENSOR +#define ADC1_CH4 ADC_CHANNEL_VREFINT + +#define ADC2_CH1 ADC_CHANNEL_7 +#define ADC2_CH2 ADC_CHANNEL_9 +#define ADC2_CH3 ADC_CHANNEL_14 +#define ADC2_CH4 ADC_CHANNEL_15 + +#define ADC1_CH1_PIN GPIO_PIN_6 +#define ADC1_CH1_PORT GPIOA +#define ADC1_CH1_ENABLE_PORT_CLK __HAL_RCC_GPIOA_CLK_ENABLE() +#define ADC1_CH2_PIN GPIO_PIN_0 +#define ADC1_CH2_PORT GPIOB +#define ADC1_CH2_ENABLE_PORT_CLK __HAL_RCC_GPIOB_CLK_ENABLE() +#define ADC1_ENABLE_CLK __ADC1_CLK_ENABLE() + +#define ADC2_CH1_PIN GPIO_PIN_7 +#define ADC2_CH1_PORT GPIOA +#define ADC2_CH1_ENABLE_PORT_CLK __HAL_RCC_GPIOA_CLK_ENABLE() +#define ADC2_CH2_PIN GPIO_PIN_1 +#define ADC2_CH2_PORT GPIOB +#define ADC2_CH2_ENABLE_PORT_CLK __HAL_RCC_GPIOB_CLK_ENABLE() +#define ADC2_CH3_PIN GPIO_PIN_4 +#define ADC2_CH3_PORT GPIOC +#define ADC2_CH3_ENABLE_PORT_CLK __HAL_RCC_GPIOC_CLK_ENABLE() +#define ADC2_CH4_PIN GPIO_PIN_5 +#define ADC2_CH4_PORT GPIOC +#define ADC2_CH4_ENABLE_PORT_CLK __HAL_RCC_GPIOC_CLK_ENABLE() +#define ADC2_ENABLE_CLK __ADC2_CLK_ENABLE() + +#define ADC_DMA_CHANNEL DMA_CHANNEL_0 +#define ADC_DMA_STREAM DMA2_Stream0 +#define ADC_DMA_IRQn DMA2_Stream0_IRQn +#define ADC_DMA_IRQHandler DMA2_Stream0_IRQHandler +#define ADC_ENABLE_DMA_CLK __HAL_RCC_DMA2_CLK_ENABLE() + +#define ADC_TIMER TIM4 +#define ENABLE_ADC_TIMER_CLK __HAL_RCC_TIM4_CLK_ENABLE() +#define ADC_TIMER_IRQn TIM4_IRQn +#define ADC_TIMER_IRQHandler TIM4_IRQHandler + +// temperature conversion functions +#define TEMP_V25 0.76// ADC voltage at 25 degrees in V +#define TEMP_INV_SLOPE 400.0// ADC slope in mV/degree + +// general voltage conversion +#define VOLTAGE_DELTA 0.000805664 +#define VOLTAGE_GAIN 1.529411765 // private variables +ADC_HandleTypeDef hadc1; +ADC_HandleTypeDef hadc2; +DMA_HandleTypeDef hdma_adc1; +TIM_HandleTypeDef ADC_TIM_Handle; + +uint32_t adc_data[4];// temporal buffer to store ADC data before conversion +uint16_t adc_period_ms; + +// private functions +uint16_t adc_convert_temperature(uint16_t value) +{ + float conv_value; + + conv_value=(value*VOLTAGE_DELTA-TEMP_V25)*TEMP_INV_SLOPE+25.0; + + return conv_value*(1<<10);// fixed point format 6 | 10 +} + +uint16_t adc_convert_vrefint(uint16_t value) +{ + float conv_value; + + conv_value=value*VOLTAGE_DELTA; + + return conv_value*(1<<12); +} + +uint16_t adc_convert_voltage(uint16_t value) +{ + float conv_value; + + conv_value=value*VOLTAGE_DELTA*VOLTAGE_GAIN; + + return conv_value*(1<<12); +} // interrupt handlers +void ADC_TIMER_IRQHandler(void) +{ + uint32_t capture; + + if(__HAL_TIM_GET_FLAG(&ADC_TIM_Handle, TIM_FLAG_CC4) != RESET) + { + if(__HAL_TIM_GET_IT_SOURCE(&ADC_TIM_Handle, TIM_IT_CC4) !=RESET) + { + __HAL_TIM_CLEAR_IT(&ADC_TIM_Handle, TIM_IT_CC4); + capture = HAL_TIM_ReadCapturedValue(&ADC_TIM_Handle, TIM_CHANNEL_4); + __HAL_TIM_SET_COMPARE(&ADC_TIM_Handle, TIM_CHANNEL_4, (capture + adc_period_ms)); + } + } + /* TIM Update event */ + if(__HAL_TIM_GET_FLAG(&ADC_TIM_Handle, TIM_FLAG_UPDATE) != RESET) + if(__HAL_TIM_GET_IT_SOURCE(&ADC_TIM_Handle, TIM_IT_UPDATE) !=RESET) + __HAL_TIM_CLEAR_IT(&ADC_TIM_Handle, TIM_IT_UPDATE); + /* TIM Break input event */ + if(__HAL_TIM_GET_FLAG(&ADC_TIM_Handle, TIM_FLAG_BREAK) != RESET) + if(__HAL_TIM_GET_IT_SOURCE(&ADC_TIM_Handle, TIM_IT_BREAK) !=RESET) + __HAL_TIM_CLEAR_IT(&ADC_TIM_Handle, TIM_IT_BREAK); + /* TIM Trigger detection event */ + if(__HAL_TIM_GET_FLAG(&ADC_TIM_Handle, TIM_FLAG_TRIGGER) != RESET) + if(__HAL_TIM_GET_IT_SOURCE(&ADC_TIM_Handle, TIM_IT_TRIGGER) !=RESET) + __HAL_TIM_CLEAR_IT(&ADC_TIM_Handle, TIM_IT_TRIGGER); + /* TIM commutation event */ + if(__HAL_TIM_GET_FLAG(&ADC_TIM_Handle, TIM_FLAG_COM) != RESET) + if(__HAL_TIM_GET_IT_SOURCE(&ADC_TIM_Handle, TIM_IT_COM) !=RESET) + __HAL_TIM_CLEAR_IT(&ADC_TIM_Handle, TIM_FLAG_COM); +} + +void ADC_DMA_IRQHandler(void) +{ + uint16_t value; + + /* Transfer Error Interrupt management ***************************************/ + if(__HAL_DMA_GET_FLAG(&hdma_adc1, __HAL_DMA_GET_TE_FLAG_INDEX(&hdma_adc1)) != RESET) + if(__HAL_DMA_GET_IT_SOURCE(&hdma_adc1, DMA_IT_TE) != RESET) + __HAL_DMA_CLEAR_FLAG(&hdma_adc1, __HAL_DMA_GET_TE_FLAG_INDEX(&hdma_adc1)); + /* FIFO Error Interrupt management ******************************************/ + if(__HAL_DMA_GET_FLAG(&hdma_adc1, __HAL_DMA_GET_FE_FLAG_INDEX(&hdma_adc1)) != RESET) + if(__HAL_DMA_GET_IT_SOURCE(&hdma_adc1, DMA_IT_FE) != RESET) + __HAL_DMA_CLEAR_FLAG(&hdma_adc1, __HAL_DMA_GET_FE_FLAG_INDEX(&hdma_adc1)); + /* Direct Mode Error Interrupt management ***********************************/ + if(__HAL_DMA_GET_FLAG(&hdma_adc1, __HAL_DMA_GET_DME_FLAG_INDEX(&hdma_adc1)) != RESET) + if(__HAL_DMA_GET_IT_SOURCE(&hdma_adc1, DMA_IT_DME) != RESET) + __HAL_DMA_CLEAR_FLAG(&hdma_adc1, __HAL_DMA_GET_DME_FLAG_INDEX(&hdma_adc1)); + /* Half Transfer Complete Interrupt management ******************************/ + if(__HAL_DMA_GET_FLAG(&hdma_adc1, __HAL_DMA_GET_HT_FLAG_INDEX(&hdma_adc1)) != RESET) + if(__HAL_DMA_GET_IT_SOURCE(&hdma_adc1, DMA_IT_HT) != RESET) + __HAL_DMA_CLEAR_FLAG(&hdma_adc1, __HAL_DMA_GET_HT_FLAG_INDEX(&hdma_adc1)); + /* Transfer Complete Interrupt management ***********************************/ + if(__HAL_DMA_GET_FLAG(&hdma_adc1, __HAL_DMA_GET_TC_FLAG_INDEX(&hdma_adc1)) != RESET) + if(__HAL_DMA_GET_IT_SOURCE(&hdma_adc1, DMA_IT_TC) != RESET) + { + __HAL_DMA_CLEAR_FLAG(&hdma_adc1, __HAL_DMA_GET_TC_FLAG_INDEX(&hdma_adc1)); + value=adc_convert_voltage(adc_data[0]&0x0000FFFF); + ram_data[BIOLOID_ADC_CH1_L]=value%256; + ram_data[BIOLOID_ADC_CH1_H]=value/256; + value=adc_convert_voltage((adc_data[0]&0xFFFF0000)>>16); + ram_data[BIOLOID_ADC_CH2_L]=value%256; + ram_data[BIOLOID_ADC_CH2_H]=value/256; + value=adc_convert_voltage(adc_data[1]&0x0000FFFF); + ram_data[BIOLOID_ADC_CH3_L]=value%256; + ram_data[BIOLOID_ADC_CH3_H]=value/256; + value=adc_convert_voltage((adc_data[1]&0xFFFF0000)>>16); + ram_data[BIOLOID_ADC_CH4_L]=value%256; + ram_data[BIOLOID_ADC_CH4_H]=value/256; + value=adc_convert_temperature(adc_data[2]&0x0000FFFF); + ram_data[BIOLOID_ADC_TEMP_L]=value%256; + ram_data[BIOLOID_ADC_TEMP_H]=value/256; + value=adc_convert_voltage((adc_data[2]&0xFFFF0000)>>16); + ram_data[BIOLOID_ADC_CH6_L]=value%256; + ram_data[BIOLOID_ADC_CH6_H]=value/256; + value=adc_convert_vrefint(adc_data[3]&0x0000FFFF); + ram_data[BIOLOID_ADC_VREF_L]=value%256; + ram_data[BIOLOID_ADC_VREF_H]=value/256; + value=adc_convert_voltage((adc_data[3]&0xFFFF0000)>>16); + ram_data[BIOLOID_ADC_CH8_L]=value%256; + ram_data[BIOLOID_ADC_CH8_H]=value/256; + } +} // public functions void adc_init(void) { - ADC_CommonInitTypeDef ADC_CommonInitStructure; - ADC_InitTypeDef ADC_InitStructure; - GPIO_InitTypeDef GPIO_InitStructure; - DMA_InitTypeDef DMA_InitStructure; + GPIO_InitTypeDef GPIO_InitStruct; + ADC_MultiModeTypeDef multimode; + ADC_ChannelConfTypeDef sConfig; + TIM_ClockConfigTypeDef sClockSourceConfig; + TIM_MasterConfigTypeDef sMasterConfig; + TIM_OC_InitTypeDef TIM_OCInitStructure; + uint32_t capture; + + /* initialize the internal variables */ + adc_period_ms=840;// equivalent to 10 ms + ram_data[BIOLOID_ADC_PERIOD]=84; /* enable clocks */ - RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE); - RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); - RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC2, ENABLE); - RCC_AHB1PeriphClockCmd(ADC1_CH2_PORT_CLK | ADC1_CH3_PORT_CLK | ADC1_CH4_PORT_CLK, ENABLE); - RCC_AHB1PeriphClockCmd(ADC2_CH1_PORT_CLK | ADC2_CH2_PORT_CLK | ADC2_CH3_PORT_CLK | ADC2_CH4_PORT_CLK, ENABLE); - - /* DMA Config */ - DMA_InitStructure.DMA_Channel = DMA_Channel_0; - DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ram_data[50]; - DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC_CCR_ADDRESS; - DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; - DMA_InitStructure.DMA_BufferSize = 4; - DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; - DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; - DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word; - DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; - DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; - DMA_InitStructure.DMA_Priority = DMA_Priority_High; - DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable; - DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full; - DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; - DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; - DMA_Init(DMA2_Stream0, &DMA_InitStructure); - - /* DMA2_Stream0 enable */ - DMA_Cmd(DMA2_Stream0, ENABLE); + ADC1_CH1_ENABLE_PORT_CLK; + ADC1_CH2_ENABLE_PORT_CLK; + ADC2_CH1_ENABLE_PORT_CLK; + ADC2_CH2_ENABLE_PORT_CLK; + ADC2_CH3_ENABLE_PORT_CLK; + ADC2_CH4_ENABLE_PORT_CLK; + + ADC_ENABLE_DMA_CLK; + + ADC1_ENABLE_CLK; + /* configure ADC1 */ + hadc1.Instance = ADC1; + hadc1.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV8; + hadc1.Init.Resolution = ADC_RESOLUTION12b; + hadc1.Init.ScanConvMode = ENABLE; + hadc1.Init.ContinuousConvMode = DISABLE;// because it is triggered by a timer + hadc1.Init.DiscontinuousConvMode = DISABLE; + hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISINGFALLING; + hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T4_CC4; + hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT; + hadc1.Init.NbrOfConversion = 4; + hadc1.Init.DMAContinuousRequests = ENABLE; + hadc1.Init.EOCSelection = EOC_SEQ_CONV; + HAL_ADC_Init(&hadc1); + + multimode.Mode = ADC_DUALMODE_REGSIMULT; + multimode.DMAAccessMode = ADC_DMAACCESSMODE_2; + multimode.TwoSamplingDelay = ADC_TWOSAMPLINGDELAY_20CYCLES; + HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode); + + /* configure ADC1 channels */ + sConfig.Channel = ADC1_CH1; + sConfig.Rank = 1; + sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES; + HAL_ADC_ConfigChannel(&hadc1, &sConfig); + + sConfig.Channel = ADC1_CH2; + sConfig.Rank = 2; + HAL_ADC_ConfigChannel(&hadc1, &sConfig); + + sConfig.Channel = ADC1_CH3; + sConfig.Rank = 3; + HAL_ADC_ConfigChannel(&hadc1, &sConfig); + + sConfig.Channel = ADC1_CH4; + sConfig.Rank = 4; + HAL_ADC_ConfigChannel(&hadc1, &sConfig); /* configure GPIO */ - GPIO_InitStructure.GPIO_Pin = ADC1_CH2_PIN | ADC2_CH2_PIN; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN; - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; - GPIO_Init(ADC1_CH2_PORT, &GPIO_InitStructure); - - GPIO_InitStructure.GPIO_Pin = ADC1_CH3_PIN | ADC1_CH4_PIN | ADC2_CH1_PIN | ADC2_CH3_PIN | ADC2_CH4_PIN; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN; - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; - GPIO_Init(ADC2_CH1_PORT, &GPIO_InitStructure); - - /* ADC Common Init */ - ADC_CommonInitStructure.ADC_Mode = ADC_DualMode_RegSimult; - ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4; - ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_2; - ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles; - ADC_CommonInit(&ADC_CommonInitStructure); - - /* ADC1 configuration */ - ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b; - ADC_InitStructure.ADC_ScanConvMode = ENABLE; - ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; - ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; - ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1; - ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; - ADC_InitStructure.ADC_NbrOfConversion = 4; - ADC_Init(ADC1, &ADC_InitStructure); - - /* ADC1 regular channels 10, 11 configuration */ - ADC_RegularChannelConfig(ADC1, ADC1_CH1, 1, ADC_SampleTime_480Cycles); - ADC_RegularChannelConfig(ADC1, ADC1_CH2, 2, ADC_SampleTime_480Cycles); - ADC_RegularChannelConfig(ADC1, ADC1_CH3, 3, ADC_SampleTime_480Cycles); - ADC_RegularChannelConfig(ADC1, ADC1_CH4, 4, ADC_SampleTime_480Cycles); - - /* ADC1 configuration */ - ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b; - ADC_InitStructure.ADC_ScanConvMode = ENABLE; - ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; - ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; - ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1; - ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; - ADC_InitStructure.ADC_NbrOfConversion = 4; - ADC_Init(ADC2, &ADC_InitStructure); - - /* ADC1 regular channels 10, 11 configuration */ - ADC_RegularChannelConfig(ADC2, ADC2_CH1, 1, ADC_SampleTime_480Cycles); - ADC_RegularChannelConfig(ADC2, ADC2_CH2, 2, ADC_SampleTime_480Cycles); - ADC_RegularChannelConfig(ADC2, ADC2_CH3, 3, ADC_SampleTime_480Cycles); - ADC_RegularChannelConfig(ADC2, ADC2_CH4, 4, ADC_SampleTime_480Cycles); - - /* Enable DMA request after last transfer (Multi-ADC mode) */ - ADC_MultiModeDMARequestAfterLastTransferCmd(ENABLE); - - /* Enable ADC1 */ - ADC_Cmd(ADC1, ENABLE); - - /* Enable ADC2 */ - ADC_Cmd(ADC2, ENABLE); - - /* Start ADC1 Software Conversion */ - ADC_SoftwareStartConv(ADC1); + GPIO_InitStruct.Pin = ADC1_CH1_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(ADC1_CH1_PORT, &GPIO_InitStruct); + GPIO_InitStruct.Pin = ADC1_CH2_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(ADC1_CH2_PORT, &GPIO_InitStruct); + + ADC2_ENABLE_CLK; + /* configure ADC1 */ + hadc2.Instance = ADC2; + hadc2.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV8; + hadc2.Init.Resolution = ADC_RESOLUTION12b; + hadc2.Init.ScanConvMode = ENABLE; + hadc2.Init.ContinuousConvMode = DISABLE;// because it is triggered by a timer + hadc2.Init.DiscontinuousConvMode = DISABLE; + hadc2.Init.DataAlign = ADC_DATAALIGN_RIGHT; + hadc2.Init.NbrOfConversion = 4; + hadc2.Init.DMAContinuousRequests = ENABLE; + hadc2.Init.EOCSelection = EOC_SEQ_CONV; + HAL_ADC_Init(&hadc2); + + multimode.Mode = ADC_DUALMODE_REGSIMULT; + multimode.DMAAccessMode = ADC_DMAACCESSMODE_2; + multimode.TwoSamplingDelay = ADC_TWOSAMPLINGDELAY_20CYCLES; + HAL_ADCEx_MultiModeConfigChannel(&hadc2, &multimode); + + /* configure ADC2 channels */ + sConfig.Channel = ADC2_CH1; + sConfig.Rank = 1; + sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES; + HAL_ADC_ConfigChannel(&hadc2, &sConfig); + + sConfig.Channel = ADC2_CH2; + sConfig.Rank = 2; + HAL_ADC_ConfigChannel(&hadc2, &sConfig); + + sConfig.Channel = ADC2_CH3; + sConfig.Rank = 3; + HAL_ADC_ConfigChannel(&hadc2, &sConfig); + + sConfig.Channel = ADC2_CH4; + sConfig.Rank = 4; + HAL_ADC_ConfigChannel(&hadc2, &sConfig); + + /* configure GPIO */ + GPIO_InitStruct.Pin = ADC2_CH1_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(ADC2_CH1_PORT, &GPIO_InitStruct); + GPIO_InitStruct.Pin = ADC2_CH2_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(ADC2_CH2_PORT, &GPIO_InitStruct); + GPIO_InitStruct.Pin = ADC2_CH3_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(ADC2_CH3_PORT, &GPIO_InitStruct); + GPIO_InitStruct.Pin = ADC2_CH4_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(ADC2_CH4_PORT, &GPIO_InitStruct); + + /* initialize DMA */ + hdma_adc1.Instance = DMA2_Stream0; + hdma_adc1.Init.Channel = DMA_CHANNEL_0; + hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY; + hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_adc1.Init.MemInc = DMA_MINC_ENABLE; + hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; + hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; + hdma_adc1.Init.Mode = DMA_CIRCULAR; + hdma_adc1.Init.Priority = DMA_PRIORITY_LOW; + hdma_adc1.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + HAL_DMA_Init(&hdma_adc1); + + __HAL_LINKDMA(&hadc1,DMA_Handle,hdma_adc1); + + HAL_NVIC_SetPriority(ADC_DMA_IRQn, 3, 1); + HAL_NVIC_EnableIRQ(ADC_DMA_IRQn); + + /* configure the timer to generate the internal trigger */ + ENABLE_ADC_TIMER_CLK; + ADC_TIM_Handle.Instance=ADC_TIMER; + ADC_TIM_Handle.Init.Period = 0xFFFF; + ADC_TIM_Handle.Init.Prescaler = 1000; + ADC_TIM_Handle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; + ADC_TIM_Handle.Init.CounterMode = TIM_COUNTERMODE_UP; + HAL_NVIC_SetPriority(ADC_TIMER_IRQn, 3, 1); + HAL_NVIC_EnableIRQ(ADC_TIMER_IRQn); + /* use the internal clock */ + sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; + HAL_TIM_ConfigClockSource(&ADC_TIM_Handle, &sClockSourceConfig); + HAL_TIM_OC_Init(&ADC_TIM_Handle); + /* disable master/slave mode */ + sMasterConfig.MasterOutputTrigger = TIM_TRGO_OC4REF; + sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; + HAL_TIMEx_MasterConfigSynchronization(&ADC_TIM_Handle, &sMasterConfig); + /* configure ouptut counter channel 4 */ + TIM_OCInitStructure.OCMode = TIM_OCMODE_TOGGLE; + TIM_OCInitStructure.OCPolarity = TIM_OCPOLARITY_HIGH; + TIM_OCInitStructure.OCFastMode = TIM_OCFAST_DISABLE; + capture = HAL_TIM_ReadCapturedValue(&ADC_TIM_Handle, TIM_CHANNEL_4); + TIM_OCInitStructure.Pulse = capture+adc_period_ms; + HAL_TIM_OC_ConfigChannel(&ADC_TIM_Handle, &TIM_OCInitStructure,TIM_CHANNEL_4); + + /* start ADC operation */ + HAL_ADC_Start(&hadc2); + HAL_ADCEx_MultiModeStart_DMA(&hadc1,adc_data,4); + adc_start(); } -uint16_t adc_get_temperature(void) +void adc_start(void) { - return 0x0000; + ram_data[BIOLOID_ADC_CNTRL]|=0x01; + HAL_TIM_OC_Start_IT(&ADC_TIM_Handle, TIM_CHANNEL_4); } + +void adc_set_period(uint8_t period_ms) +{ + adc_period_ms=period_ms*84; +} + +void adc_stop(void) +{ + ram_data[BIOLOID_ADC_CNTRL]&=0xFE; + HAL_TIM_OC_Stop_IT(&ADC_TIM_Handle, TIM_CHANNEL_4); +} + diff --git a/src/bioloid_dyn_master_sensors.c b/src/bioloid_dyn_master_sensors.c index 783f116c17276b6485735206372ba3758a7dae24..ff619e83fd9ab862e97fbc157b756b3723287c6a 100755 --- a/src/bioloid_dyn_master_sensors.c +++ b/src/bioloid_dyn_master_sensors.c @@ -75,9 +75,4 @@ void bioloid_dyn_master_sensors_init(void) dyn_master_init(&bioloid_dyn_master_sensors,&bioloid_dyn_master_sensors_comm); bioloid_dyn_master_sensors.set_rx_mode=bioloid_dyn_master_sensors_set_rx_mode; bioloid_dyn_master_sensors.set_tx_mode=bioloid_dyn_master_sensors_set_tx_mode; - - if(dyn_master_ping(&bioloid_dyn_master_sensors,0xC0)==DYN_SUCCESS) - gpio_set_led(RXD_LED); - else - gpio_clear_led(RXD_LED); } diff --git a/src/bioloid_stm32.c b/src/bioloid_stm32.c index 8c9688988924eb475345fd6bf33728f666450102..2b36940662c74c346e0ede9cd009caed0ea6c80c 100644 --- a/src/bioloid_stm32.c +++ b/src/bioloid_stm32.c @@ -2,6 +2,7 @@ #include "gpio.h" #include "eeprom.h" #include "ram.h" +#include "adc_dma.h" #include "bioloid_time.h" #include "bioloid_dyn_slave.h" #include "bioloid_dyn_master_sensors.h" @@ -15,6 +16,8 @@ int32_t main(void) EE_Init(); /* initialize the ram module */ ram_init(); + /* initialize the ADC module */ + adc_init(); /* initialize the time module */ bioloid_time_init(); /* initialize the dynamixel slave interface */