stm8L ADC多通通DMA采集和EEPROM一起使用解决死机和数据错位问题——寄存器

一、简介

现象:本实验在使用ADC+DMA+EEPOM实验室,在eeprom写入数据的时候单片机死机,我在写eerpom时关闭adc和关闭dma,写完之后开启adc和dma单片机就不死机了,然后就出现adc数据错位的问题,经过一天的修改实验,现已没有死机和数据错位现象。本实验采用iar平台所做,参考手册为RM0031手册,采用寄存器方式。

二、stm8L的adc和dma寄存器:

1、时钟寄存器-adc和dma

stm8L ADC多通通DMA采集和EEPROM一起使用解决死机和数据错位问题——寄存器_第1张图片

相关代码:

CLK_PCKENR2_PCKEN20 = 1;      /* 开启adc时钟 */
CLK_PCKENR2_PCKEN24 = 1;     /* 开启DMA时钟 */

2、adc其他相关寄存器

stm8L ADC多通通DMA采集和EEPROM一起使用解决死机和数据错位问题——寄存器_第2张图片
 

stm8L ADC多通通DMA采集和EEPROM一起使用解决死机和数据错位问题——寄存器_第3张图片

相关代码:

  ADC1_CR1_ADON = 1;            /* 使能adc ADCON wake up from power down mode */
  ADC1_CR1_CONT = 1;            /* 0:单次转换 1:连续转换 */  

  ADC1_CR1_EOCIE = 0;           /* 关闭adc中断 */

stm8L ADC多通通DMA采集和EEPROM一起使用解决死机和数据错位问题——寄存器_第4张图片

相关代码:

ADC1_CR2_PRESC = 0;           /* select a sample time of 10 us f(ADC_CLK)=CK */

ADC1_CR2_SMTP1 = 0x06;        /* 外部0-23通道采样时间24 */

stm8L ADC多通通DMA采集和EEPROM一起使用解决死机和数据错位问题——寄存器_第5张图片

相关代码:

ADC1_CR3_SMTP2 = 0x06;        /* 内部参考电压通道采样时间为24  */

stm8L ADC多通通DMA采集和EEPROM一起使用解决死机和数据错位问题——寄存器_第6张图片

相关代码:(我这里使用通道7、8 、9)

  /* 选择ADC通道 */
  ADC1_SQR4_CHSEL_S7 = 1;       //打开adc通道7
  ADC1_TRIGR4_TRIG7 = 1;        //关闭通道7的施密特触发器
  ADC1_SQR3_CHSEL_S8 = 1;       //选择通道8
  ADC1_TRIGR3_TRIG8 = 1;        //关闭通道8的施密特触发器
  ADC1_SQR3_CHSEL_S9 = 1;       //选择通道9
  ADC1_TRIGR3_TRIG9 = 1;        //关闭通道9的施密特触发器

stm8L ADC多通通DMA采集和EEPROM一起使用解决死机和数据错位问题——寄存器_第7张图片

相关代码:

ADC1_SQR1_DMAOFF = 0;         /* 使能DMA */

 

3、dma相关寄存器

stm8L ADC多通通DMA采集和EEPROM一起使用解决死机和数据错位问题——寄存器_第8张图片

相关代码:
  SYSCFG_RMPCR1_ADC1DMA_REMAP = 1;       /* 设置DMA通道 */

 

stm8L ADC多通通DMA采集和EEPROM一起使用解决死机和数据错位问题——寄存器_第9张图片

相关代码:
  DMA1_C1CR_CIRC = 1;     /* 设置模式 */
  DMA1_C1CR_MINCDEC = 1;  /* 设置增还是减去地址 */
  DMA1_C1CR_TCIE = 1;  /* 使能传送完一组数据中断 */
  DMA1_C1CR_EN = 1;   /* 使能DMA1通道 */

 

stm8L ADC多通通DMA采集和EEPROM一起使用解决死机和数据错位问题——寄存器_第10张图片

相关代码:
  DMA1_C1SPR_PL0 = 0;    /* 设置通道优先级 */
  DMA1_C1SPR_PL1 = 1;
 
  DMA1_C1SPR_TSIZE = 1;     /* 设置传送位数 */

 

stm8L ADC多通通DMA采集和EEPROM一起使用解决死机和数据错位问题——寄存器_第11张图片

相关代码:
  DMA1_C1NDTR = 12;    /* 设置传送字节 */

stm8L ADC多通通DMA采集和EEPROM一起使用解决死机和数据错位问题——寄存器_第12张图片

相关代码:
  DMA1_GCSR_GEN = 1;   /* DMA全局使能 */

三、部分实验代码:

1、adc配置

void ADC_Init(void)
{
  CLK_PCKENR2_PCKEN20 = 1;      /* 开启adc时钟 */
  
  ADC1_CR1_ADON = 1;            /* 使能adc ADCON wake up from power down mode */
  
  ADC1_CR1_CONT = 1;            /* 0:单次转换 1:连续转换 */  

  ADC1_CR2_PRESC = 0;           /* select a sample time of 10 us f(ADC_CLK)=CK */
  //   0: f(ADC_CLK) = CK
  
  //   1: f(ADC_CLK) = CK/2  //系统时钟此时为默认的16M/8=2M,这里分频后,fadc=2M/2=1M
  
  
  //ADC1_SQR1_DMAOFF = 1;         /* 关闭DMA */
  ADC1_SQR1_DMAOFF = 0;         /* 使能DMA */
  
  
  ADC1_CR3_SMTP2 = 0x06;        /* 内部参考电压通道采样时间为24  */
  //000: 4 ADC clock cycles
    
  //001: 9 ADC clock cycles
    
  //010: 16 ADC clock cycles
    
  //011: 24 ADC clock cycles
    
  //100: 48 ADC clock cycles
    
  //101: 96 ADC clock cycles
    
  //110: 192 ADC clock cycles
    
  //111: 384 ADC clock cycles
  
  ADC1_CR2_SMTP1 = 0x06;        /* 外部0-23通道采样时间24 */
  
  /* 选择ADC通道 */
  ADC1_SQR4_CHSEL_S7 = 1;       //打开adc通道7
  ADC1_TRIGR4_TRIG7 = 1;        //关闭通道7的施密特触发器
  
  ADC1_SQR3_CHSEL_S8 = 1;       //选择通道8
  ADC1_TRIGR3_TRIG8 = 1;        //关闭通道8的施密特触发器
  
  ADC1_SQR3_CHSEL_S9 = 1;       //选择通道9
  ADC1_TRIGR3_TRIG9 = 1;        //关闭通道9的施密特触发器
   
  //ADC1_CR1_EOCIE = 1;           /* 开启adc中断 */
}

2、dma初始化

void ADC1_DMA_Init(void)
{
  /* 开启DMA时钟 */
  CLK_PCKENR2_PCKEN24 = 1;
  
  /* 设置DMA通道 */
  SYSCFG_RMPCR1_ADC1DMA_REMAP = 1;
  
  /* 设置传送字节 */
  DMA1_C1NDTR = 12;
  
  /* 设置通道优先级 */
  DMA1_C1SPR_PL0 = 0;
  DMA1_C1SPR_PL1 = 1;
  
  /* 设置传送方向 */
  DMA1_C1CR_DIR = 0;
  
  /* 设置模式 */
  DMA1_C1CR_CIRC = 1;
  
  /* 设置增还是减去地址 */
  DMA1_C1CR_MINCDEC = 1;
  
  /* 设置传送位数 */
  DMA1_C1SPR_TSIZE = 1;
  
  /* 使能传送完一组数据中断 */
  //DMA1_C1CR_HTIE = 1;
  DMA1_C1CR_TCIE = 1;
  
  /* 设置DMA通道1外设地址 */
  DMA1_C1PARH=(uint8_t)((uint16_t)ADC_DRH_ADRESS >> (uint8_t)8);
  DMA1_C1PARL=(uint8_t)ADC_DRH_ADRESS;
  
  /* 设置DMA通道1内存地址 */
  DMA1_C1M0ARH=(uint8_t)((uint16_t)&adc_dmaval >> (uint8_t)8);
  DMA1_C1M0ARL=(uint8_t)&adc_dmaval;
  
  
  /* 使能DMA1通道 */
  DMA1_C1CR_EN = 1;
  
  /* DMA全局使能 */
  DMA1_GCSR_GEN = 1;
}

 

3、中断函数

#pragma vector=DMA1_CH1_TC_vector
__interrupt void DMA1_CH1_TC_ISR(void)

{

  if(DMA1_C1SPR_TCIF == 1)
  {
    DMA1_C1SPR_TCIF = 0;

   /* 直接从变量中读取数据 */

  }

}

 

4、暂时关闭adc

本实验采用关闭adc时钟的方式关闭adc,在写入eeprom数据前,关闭adc,在写入eeprom数据后开启adc时钟。

void ADC1_Close(void)
{
  CLK_PCKENR2_PCKEN20 = 0;      /* 开启adc时钟 */
}

5、开启adc

在写完eeprom数据后,开启adc时钟。

void ADC1_ReStart(void)
{  
  CLK_PCKENR2_PCKEN20 = 1;      /* 开启adc时钟 */
}

你可能感兴趣的:(STM8,单片机,stm32,嵌入式)