void ADC_Init(void) //初始化ADC,即初始化ADC
{
CLK_PCKENR2 |= SETBIT3; //开ADC时钟
ADC_CR2 = 0x08; // A/D结果数据右对齐
ADC_CR1 = 0x00; // ADC时钟=主时钟/2=1MHZ
// ADC转换模式=单次
// 禁止ADC转换
ADC_TDRH = 0x00; //禁止施密特触发,对应的通道置1
//ADC_TDRL = 0x38; //0b00111000 对应3、4、5通道禁止
ADC_TDRL = 0x30; //0b00111000 对应3、4、5通道禁止,打开3通道
ADC_CR1 = 0x01; // CR1寄存器的最低位置1,使能ADC转换
Delay_us(8); // 延时一段时间,至少7uS,保证ADC模块的
}
u16 ADC_Get_Voltage(unsigned char channel)//获取对应通道电压量化值
{
u16 vt;
u16 DRL,DRH;
ADC_CSR = ADC_CSR & 0x80; // 清除通道
ADC_CSR = ADC_CSR | channel; // 选择通道
ADC_CR1 = ADC_CR1 | 0x01; // 再次将CR1寄存器的最低位置1
// 使能ADC转换
while((ADC_CSR & 0x80) == 0); // 等待ADC结束
DRL = ADC_DRL; // 读出ADC结果的低8位
DRH = ADC_DRH; // 读出ADC结果的高8位
ADC_CSR &= CLRBIT7;//清转换结束标志
vt=(DRH<<8)|DRL;//量化值,需要 Vt/1024*Vs(Vs=3.3V )
vt=(int)(vt*VIN*100/1024);//内部参考输入电压,100是小数点后2位都化为整数
//vt=(int)(vt*VIN*1000/1024);//内部参考输入电压,1000是小数点后3位都化为整数
return vt;
} 飞龙xyj 发表于 2015-6-30 19:01
楼主您好,我今天用连续扫描模式调通了8个模拟通道(AIN0-AIN7)的AD采集,看了下您的代码,发现有两处问题 ...
非常感谢,按照“飞龙xyj”的方法,增加了如下指令,
/* Clear the ADC1 channels */
ADC1->CSR &= (uint8_t)(~ADC1_CSR_CH);
/* Select the ADC1 channel */
ADC1->CSR |= (uint8_t)(ADC1_CHANNEL_7);
终于解决了ADC单次扫描,输出缓存寄存器无数据的问题,非常感谢! 飞龙xyj 发表于 2015-6-30 19:01
楼主您好,我今天用连续扫描模式调通了8个模拟通道(AIN0-AIN7)的AD采集,看了下您的代码,发现有两处问题 ...
非常感谢,按照“飞龙xyj”的方法,增加了如下指令,
/* Clear the ADC1 channels */
ADC1->CSR &= (uint8_t)(~ADC1_CSR_CH);
/* Select the ADC1 channel */
ADC1->CSR |= (uint8_t)(ADC1_CHANNEL_7);
终于解决了ADC单次扫描,输出缓存寄存器无数据的问题,非常感谢! 使用的芯片为:STM8S003F3P,ADC配置为单次扫描模式,并设置ADC转化完成中断,具体如下:
void ADC1_Config(void)
{
ADC1_DeInit();
/* Clear the SPSEL bits */
ADC1->CR1 &= (uint8_t)(0x8F); // 1000 1111
/* Set the prescaler of ADC : fADC1 = fcpu/4 =4MHz*/
ADC1->CR1 |= (uint8_t)(ADC1_PRESSEL_FCPU_D4);
/* Set the single conversion mode */
ADC1->CR1 &= (uint8_t)(0xFD);// 1111 1101
/* Set the continous conversion mode */
//ADC1->CR1 |=(uint8_t)(0x02);
/* Clear the align bit */
ADC1->CR2 &= (uint8_t)(0xF7);// 1111 0111
/* Configure the data alignment */
ADC1->CR2 |= (uint8_t)(ADC1_ALIGN_RIGHT);
/* 如果定时器触发模式被选定(定时器事件作为触发源,而不是外部引脚),
那么推荐在ADC完成设置之后启动定时器和在关闭ADC之前先停止定时器。*/
/* Clear the external trigger selection bits */
ADC1->CR2 &= (uint8_t)(0xCF);// 1100 1111
/* Select TIM1 TRGO as external trigger souce */
// ADC1->CR2 |= (uint8_t)(ADC1_EXTTRIG_TIM);
/* Enable the selected external trigger */
//ADC1->CR2 |= (uint8_t)(0x40);// 0100 0000
//ADC1->CR2 &= (uint8_t)(0xBF);// 1011 1111
/* Enable the ADC1 scan mode */
//ADC1->CR2 |= (uint8_t)(ADC1_CR2_SCAN);
ADC1_ScanModeCmd(ENABLE);
/* Enables the ADC1 data store into the Data Buffer registers
rather than in the Data Register */
ADC1->CR3 |= ADC1_CR3_DBUF;
/* Clear OVR flag status */
ADC1->CR3 &= (uint8_t)(~ADC1_CR3_OVR);
// ADC1_ClearITPendingBit(ADC1_IT_EOC);
/* Disable EOC/AWD interrupts of ADC1 */
//ADC1->CSR &= (uint8_t)(0xCF);// 1100 1111
ADC1_ITConfig(ADC1_IT_EOCIE,ENABLE);//ENABLE
ADC1_ITConfig(ADC1_IT_AWDIE,DISABLE);
//ADC1_ITConfig((ADC1_IT_AWDIE|ADC1_IT_EOCIE),DISABLE);
/* Clear the ADC1 channels */
ADC1->CSR &= (uint8_t)(0xF0);//
/* Select a ADC1 channel to be converted */
// ADC1->CSR |= (uint8_t)(ADC1_CHANNEL_0);//6//5//4//3//2
/* Clear EOC flag status */
ADC1->CSR &= (uint8_t)(0x7F);// 0111 1111
/* Disable the Schmitt Trigger of all channels on ADC1*/
ADC1->TDRL |= (uint8_t)0xFF;
ADC1->TDRH |= (uint8_t)0xFF;
/*Enables or Disables the ADC1 peripheral*/
ADC1_Cmd(ENABLE);
Delay_us(500);//第一次上电后,等待ADC1的稳定
/*启动一次ADC1采样及转换*/
ADC1_Cmd(ENABLE);
}
而且我是在TIM4设置的400us时基中断中重新开启ADC1,让ADC1再进行一次新的扫描,
然后在ADC转化完成中断里,进行清除flag标志,以及做新的设置,具体如下:
INTERRUPT_HANDLER(ADC1_IRQHandler, 22)
{
/* In order to detect unexpected events during development,
it is recommended to set a breakpoint on the following instruction.
*/
//ADC1_ClearFlag(ADC1_FLAG_EOC);//ADC1_CR3_OVR
ADC1_ClearITPendingBit(ADC1_IT_EOC);
/* Clear OVR flag status */
ADC1->CR3 &= (uint8_t)(~ADC1_CR3_OVR);
/* Clear the ADC1 channels */
ADC1->CSR &= (uint8_t)(~ADC1_CSR_CH);
/* Select the ADC1 channel */
ADC1->CSR |= (uint8_t)(ADC1_CHANNEL_6);
//GPIO_WriteReverse(GPIOA,GPIO_PIN_2);
// return;
}
代码运行正常,结果满足预期,希望对其他小伙伴,提供帮助!
谢谢 学习中,感谢分亨!
页:
1
[2]