J'utilise les canaux ADC (résolution de 12 bits) d'un microcontrôleur STM32F0 pour lire les valeurs de tension dans trois points différents d'une carte. Ce que je veux faire est de lire les valeurs toutes les 2 secondes (j'ai 2 secondes pour lire les valeurs dans les trois points) et les envoyer par l'interface UART. Afin de sélectionner le canal ADC Je lis, je suis mise en œuvre des fonctions de lecture de tension comme suit:Comment lire plusieurs interfaces ADC toutes les n secondes par canal dans STM32 MCU?
uint16_t readv1(void){
//Here I try to read ADC_CHANNEL_1
//chConfig and txtbuff are global variables:
//ADC_ChannelConfTypeDef chConfig;
//char txtbuff[64];
chConfig.Channel = ADC_CHANNEL_1;
HAL_ADC_ConfigChannel(&hadc, &chConfig);
uint32_t vref = HAL_ADC_GetValue(&hadc);
uint16_t vref2 = (uint16_t) vref;
sprintf(TextBuffer, "%u\n", vref2);
HAL_UART_Transmit(&huart4, (uint8_t*)txtbuff, strlen(txtbuff), 0xFFFFFFFF);
return vref2;
}
C'est la fonction pour la numérisation d'un canal ADC. Pour lire les deux autres canaux ADC, j'utilise la même procédure en changeant simplement la valeur de n
sur la ligne chConfig.Channel = ADC_CHANNEL_n;
où n
est le numéro de canal. Notez que chConfig
est du même type de sConfig
déclaré dans la fonction MX_ADC_Init()
, mais chConfig
est une variable globale, devrait-elle être déclarée en tant que variable locale dans chaque fonction? Le problème que j'ai est que la fonction readv1
lit une tension constante (je l'ai vérifiée avec un voltimètre) mais les chiffres affichés dans le terminal via UART changent beaucoup, entre 120 et 2400. Je ne suis pas sûr d'utiliser la ligne chConfig.Channel = ADC_CHANNEL_1;
pour sélectionner un canal est bonne ou s'il y a une autre procédure à suivre. Comment pourrais-je lire correctement les valeurs de chaque ADC?
Pour faire l'analyse de l'ADC toutes les deux secondes j'utilise une minuterie de 8 MHz comme suit:
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){
if (htim->Instance==TIM3){
//Here I call the functions which read the voltage values of different ADC channels
volt1 = readv1();
readv2(volt1);
readv3(volt1);
}
}
Ceci est la fonction principale où j'initialiser les periphericals:
int main(void)
{
/* MCU Configuration----------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART4_UART_Init();
MX_ADC_Init();
MX_TIM3_Init();
/* USER CODE BEGIN 2 */
HAL_ADC_Start_IT(&hadc);
HAL_TIM_Base_Start_IT(&htim3);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
}
}
et
ci-dessous sont les fonctions d'initialisation de la minuterie et l'ADC:
/* TIM3 init function */
static void MX_TIM3_Init(void)
{
TIM_ClockConfigTypeDef sClockSourceConfig;
TIM_MasterConfigTypeDef sMasterConfig;
htim3.Instance = TIM3;
htim3.Init.Prescaler = 8000;
htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
htim3.Init.Period = 1999;
htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim3) != HAL_OK)
{
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
}
/* ADC init function */
static void MX_ADC_Init(void)
{
ADC_ChannelConfTypeDef sConfig;
/**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
*/
hadc.Instance = ADC1;
hadc.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
hadc.Init.Resolution = ADC_RESOLUTION_12B;
hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;
hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc.Init.LowPowerAutoWait = DISABLE;
hadc.Init.LowPowerAutoPowerOff = DISABLE;
hadc.Init.ContinuousConvMode = ENABLE;
hadc.Init.DiscontinuousConvMode = DISABLE;
hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc.Init.DMAContinuousRequests = DISABLE;
hadc.Init.Overrun = ADC_OVR_DATA_PRESERVED;
if (HAL_ADC_Init(&hadc) != HAL_OK)
{
Error_Handler();
}
/**Configure for the selected ADC regular channel to be converted.
*/
sConfig.Channel = ADC_CHANNEL_0;
sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;
if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
{
Error_Handler();
}
/**Configure for the selected ADC regular channel to be converted.
*/
sConfig.Channel = ADC_CHANNEL_1;
if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
{
Error_Handler();
}
/**Configure for the selected ADC regular channel to be converted.
*/
sConfig.Channel = ADC_CHANNEL_2;
if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
{
Error_Handler();
}
/**Configure for the selected ADC regular channel to be converted.
*/
sConfig.Channel = ADC_CHANNEL_4;
if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
{
Error_Handler();
}
}
volt1 = readv1(); readv2 (volt1); readv3 (volt1); Pourquoi raeadv2() et readv3() prennent le paramètre volt1 mais readv1() non? Vous avez dit "Pour lire les deux autres canaux ADC, j'utilise la même procédure en changeant simplement la valeur de n dans la ligne chConfig.Channel = ADC_CHANNEL_n, où n est le numéro de canal." Essayez d'ajouter "volatile" pour la variable volt1. – Zhifei