stm8s001 - SWIM复用为ADC输入 & ADC电压值不准确?

文章目录

  • 引脚功能
  • 软件配置
  • SWIM复用为ADC之后采样值不准确

引脚功能

stm8s001 - SWIM复用为ADC输入 & ADC电压值不准确?_第1张图片

  • STM8S001有三个ADC输入通道,但是分布在两个引脚,所以可以说只有两个可用的ADC。
  • 分别是PD6、PD5、PD3,对应AIN6、AIN5、AIN4,分布在第一脚和第八脚。
  • 我使用两个ADC
    • 具有SWIM功能的第八脚,复用为AIN5;命名为IGN
    • 第一脚,配置为AIN6;命名为MOTOn

软件配置

#define ADC_IGN_PORT            GPIOD
#define ADC_IGN_PIN             GPIO_PIN_5

#define ADC_MOTORn_PORT         GPIOD
#define ADC_MOTORn_PIN          GPIO_PIN_6

#define ADC_IGN_CHANNEL                 ADC1_CHANNEL_5
#define ADC_MOTORn_CHANNEL              ADC1_CHANNEL_6

#define ADC_VREF_VOLTAGE	        (5.0)           /**< 5V */
#define ADC_RESOLUTION_VALUE            (1024)          /**< ADC ressolution: 10bit */

/* 初始化ADC函数 */
void adc_init(void)
{
  GPIO_Init_redef(ADC_IGN_PORT, ADC_IGN_PIN, GPIO_MODE_IN_FL_NO_IT);
  GPIO_Init_redef(ADC_MOTORn_PORT, ADC_MOTORn_PIN, GPIO_MODE_IN_FL_NO_IT);

  ADC1->CR1 &= (~ADC1_CR1_ADON);
  /* Clear the align bit */
  ADC1->CR2 &= (uint8_t)(~ADC1_CR2_ALIGN);
  /* Configure the data alignment */
  ADC1->CR2 |= ADC1_ALIGN_RIGHT;

  /* Set the single conversion mode */
  ADC1->CR1 &= (uint8_t)(~ADC1_CR1_CONT);

  /* Clear the external trigger selection bits */
  ADC1->CR2 &= (uint8_t)(~ADC1_CR2_EXTSEL);

  /* Disable the selected external trigger */
  ADC1->CR2 &= (uint8_t)(~ADC1_CR2_EXTTRIG);		  		  
  /* Set the selected external trigger */
  ADC1->CR2 |= (uint8_t)(ADC1_EXTTRIG_GPIO);

  /* Clear the SPSEL bits */
  ADC1->CR1 &= (uint8_t)(~ADC1_CR1_SPSEL);
  /* Select the prescaler division factor according to ADC1_PrescalerSelection values */
  ADC1->CR1 |= (uint8_t)(ADC1_PRESSEL_FCPU_D18);

  ADC1->TDRL |= (uint8_t)0xFF;
  ADC1->TDRH |= (uint8_t)0xFF;	

  /* Enable the ADC1 peripheral */
  ADC1->CR1 |= (uint8_t)ADC1_CR1_ADON;
  
  adc_data.curr_channel = IGN;     /**< 1-MOTORn channel; 0-IGN channel */
  adc_channel_set(adc_data.curr_channel);
}

/* 设置通道函数 */
void adc_channel_set(adc_channel_name_t ch)
{
  ADC1->CSR &= (uint8_t)(~ADC1_CSR_CH);
  if(ch == IGN){
    ADC1->CSR |= (uint8_t)(ADC_IGN_CHANNEL);
  }
  else if(ch == MOTORn){
    ADC1->CSR |= (uint8_t)(ADC_MOTORn_CHANNEL);
  }
  ADC1->CR1 |= (uint8_t)ADC1_CR1_ADON;
}

/* 读取原始数据函数 */
uint16_t read_adc_orig_value(void)
{
  uint16_t temph = 0;
  uint8_t templ = 0;
  templ = ADC1->DRL;
  temph = ADC1->DRH;
  temph = (uint16_t)(templ | (uint16_t)(temph << (uint8_t)8));
  return temph;
}

SWIM复用为ADC之后采样值不准确

  • 其实并不是ADC不准确,而是外部电路导致了ADC引脚阻抗过大,从而导致采样不准确。
  • 我用IGN引脚采12V的IGN电压,开始使用了220k和22k的分压电阻,导致引脚阻抗过大,采样不准确。
    stm8s001 - SWIM复用为ADC输入 & ADC电压值不准确?_第2张图片
  • 后来使用5.6k和2k,AD值已经很接近理论值了。
  • 后来怕电流过大烧坏芯片,还是选择了56k和10k,AD值比理论值略高,经过线性处理后达到准确值。

以下是不通电压时的AD电压值。
stm8s001 - SWIM复用为ADC输入 & ADC电压值不准确?_第3张图片
也是线性的,故进行了线性换算,得出准确值。
stm8s001 - SWIM复用为ADC输入 & ADC电压值不准确?_第4张图片

float get_adc_voltage(adc_channel_name_t ch)
{
  if(ch == IGN){
    return (1.178 * adc_data.voltage_flt[ch] - 0.882);
  }
  else{
    return (adc_data.voltage_flt[ch]);
  }
}

// end
// 2019.08.10

你可能感兴趣的:(STM8)