拆分ADC

This commit is contained in:
Stone 2016-06-14 08:25:16 +00:00
parent b0dffd257e
commit 3b14dd1104
3 changed files with 261 additions and 238 deletions

View File

@ -1,8 +1,6 @@
#include "ADC.h"
#include "Platform\stm32.h"
Pin ADC_Pins[] = ADC1_PINS;
//Pin _Pins[] = ADC1_PINS;
ADConverter::ADConverter(byte line, uint channel)
{
@ -20,15 +18,17 @@ ADConverter::ADConverter(byte line, uint channel)
Buffer(Data, sizeof(Data)).Clear();
ADC_TypeDef* const g_ADCs[]= ADCS;
_ADC = g_ADCs[line - 1];
_PinCount = 0;
_ADC = nullptr;
OnInit();
}
void ADConverter::Add(Pin pin)
{
for(int i=0; i<ArrayLength(ADC_Pins); i++)
for(int i=0; i<_PinCount; i++)
{
if(ADC_Pins[i] == pin)
if(_Pins[i] == pin)
{
Channel |= (1 << i);
Count++;
@ -39,9 +39,9 @@ void ADConverter::Add(Pin pin)
void ADConverter::Remove(Pin pin)
{
for(int i=0; i<ArrayLength(ADC_Pins); i++)
for(int i=0; i<_PinCount; i++)
{
if(ADC_Pins[i] == pin)
if(_Pins[i] == pin)
{
Channel &= ~(1 << i);
Count--;
@ -54,190 +54,32 @@ void ADConverter::Open()
{
debug_printf("ADC::Open %d 共%d个通道\r\n", Line, Count);
auto at = (ADC_TypeDef*)_ADC;
/* Enable DMA clock */
#ifdef STM32F4
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
ADC_DeInit();
#else
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
ADC_DeInit(at);
#endif
/* Enable ADC and GPIOC clock */
//RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOC, ENABLE);
const int g_ADC_rccs[]= ADC_RCCS;
RCC_APB2PeriphClockCmd(g_ADC_rccs[Line - 1], ENABLE);
uint dat = 1;
for(int i=0; i<ArrayLength(Data); i++, dat <<= 1)
{
if(Channel & dat)
{
debug_printf("ADC::Init %d ", i+1);
if(i < ArrayLength(ADC_Pins))
_ports[i].Set(ADC_Pins[i]).Open();
if(i < _PinCount)
_ports[i].Set(_Pins[i]).Open();
else
debug_printf("\r\n");
}
}
/* DMA channel1 configuration */
#ifdef STM32F4
DMA_DeInit(DMA1_Stream0);
DMA_InitTypeDef dma;
DMA_StructInit(&dma);
dma.DMA_PeripheralBaseAddr = (uint)&at->DR; //ADC地址
//dma.DMA_MemoryBaseAddr = (uint)&Data; //内存地址
//dma.DMA_DIR = DMA_DIR_PeripheralSRC;
dma.DMA_BufferSize = Count;
dma.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址固定
dma.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存地址固定
dma.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //半字
dma.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
dma.DMA_Mode = DMA_Mode_Circular; //循环传输
dma.DMA_Priority = DMA_Priority_High;
//dma.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Stream0, &dma);
/* Enable DMA channel1 */
DMA_Cmd(DMA1_Stream0, ENABLE);
#else
DMA_DeInit(DMA1_Channel1);
DMA_InitTypeDef dma;
DMA_StructInit(&dma);
dma.DMA_PeripheralBaseAddr = (uint)&at->DR; //ADC地址
dma.DMA_MemoryBaseAddr = (uint)&Data; //内存地址
dma.DMA_DIR = DMA_DIR_PeripheralSRC;
dma.DMA_BufferSize = Count;
dma.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址固定
dma.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存地址固定
dma.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //半字
dma.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
dma.DMA_Mode = DMA_Mode_Circular; //循环传输
dma.DMA_Priority = DMA_Priority_High;
dma.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel1, &dma);
/* Enable DMA channel1 */
DMA_Cmd(DMA1_Channel1, ENABLE);
#endif
/* ADC configuration */
ADC_InitTypeDef adc;
ADC_StructInit(&adc);
#if defined(STM32F1) || defined(GD32)
adc.ADC_Mode = ADC_Mode_Independent; //独立ADC模式
adc.ADC_ScanConvMode = ENABLE ; //禁止扫描模式,扫描模式用于多通道采集
adc.ADC_ContinuousConvMode = ENABLE; //开启连续转换模式即不停地进行ADC转换
adc.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //不使用外部触发转换
adc.ADC_DataAlign = ADC_DataAlign_Right; //采集数据右对齐
adc.ADC_NbrOfChannel = Count; //要转换的通道数目1
ADC_Init(at, &adc);
#if defined(GD32)
RCC_ADCCLKConfig(RCC_ADCCLK_APB2_DIV6);
#else
/*配置ADC时钟为PCLK2的8分频即9MHz*/
RCC_ADCCLKConfig(RCC_PCLK2_Div8);
#endif
/*配置ADC1的通道10 11为55. 5个采样周期序列为1 */
//ADC_RegularChannelConfig(at, ADC_Channel_10, 1, ADC_SampleTime_55Cycles5);
dat = 1;
uint n = 1;
for(byte i=0; i<ArrayLength(Data); i++, dat <<= 1)
{
if(Channel & dat)
{
// 第三个参数rank必须连续
if(i < ADC_Channel_TempSensor)
ADC_RegularChannelConfig(at, i, n++, ADC_SampleTime_55Cycles5);
else
ADC_RegularChannelConfig(at, i, n++, ADC_SampleTime_239Cycles5);
}
}
if(Channel & 0x30000) ADC_TempSensorVrefintCmd(ENABLE);
/* Enable ADC DMA */
ADC_DMACmd(at, ENABLE);
/* Enable ADC */
ADC_Cmd(at, ENABLE);
/*复位校准寄存器 */
ADC_ResetCalibration(at);
/*等待校准寄存器复位完成 */
while(ADC_GetResetCalibrationStatus(at));
/* ADC校准 */
ADC_StartCalibration(at);
/* 等待校准完成*/
while(ADC_GetCalibrationStatus(at));
/* 由于没有采用外部触发所以使用软件触发ADC转换 */
ADC_SoftwareStartConvCmd(at, ENABLE);
#elif defined(STM32F0)
/* ADC DMA request in circular mode */
ADC_DMARequestModeConfig(at, ADC_DMAMode_Circular);
/* Enable ADC_DMA */
ADC_DMACmd(at, ENABLE);
/* Configure the ADC in continous mode withe a resolutuion equal to 12 bits */
adc.ADC_Resolution = ADC_Resolution_12b;
adc.ADC_ContinuousConvMode = ENABLE;
adc.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
adc.ADC_DataAlign = ADC_DataAlign_Right;
adc.ADC_ScanDirection = ADC_ScanDirection_Backward;
ADC_Init(at, &adc);
dat = 1;
for(int i=0; i<ArrayLength(Data); i++, dat <<= 1)
{
if(Channel & dat)
{
ADC_ChannelConfig(at, dat , ADC_SampleTime_55_5Cycles);
if(dat == ADC_Channel_TempSensor)
ADC_TempSensorCmd(ENABLE);
else if(dat == ADC_Channel_Vrefint)
ADC_VrefintCmd(ENABLE);
else if(dat == ADC_Channel_Vbat)
ADC_VbatCmd(ENABLE);
}
}
/* ADC Calibration */
ADC_GetCalibrationFactor(at);
/* Enable ADC */
ADC_Cmd(at, ENABLE);
// GD32F130需要20us左右的延时
Sys.Delay(2000);
/* Wait the ADCEN falg */
while(!ADC_GetFlagStatus(at, ADC_FLAG_ADEN));
/* ADC regular Software Start Conv */
ADC_StartOfConversion(at);
#endif
OnOpen();
}
ushort ADConverter::Read(Pin pin)
{
ushort dat = 1;
int n = 0;
for(int i=0; i<ArrayLength(ADC_Pins); i++, dat <<= 1)
for(int i=0; i<_PinCount; i++, dat <<= 1)
{
if(Channel & dat)
{
n++;
if(ADC_Pins[i] == pin)
if(_Pins[i] == pin)
{
return Data[n-1];
}
@ -245,62 +87,3 @@ ushort ADConverter::Read(Pin pin)
}
return 0;
}
ushort ADConverter::ReadTempSensor()
{
// 先判断有没有打开通道
#if defined(STM32F1) || defined(GD32)
if(!(Channel & (1 << ADC_Channel_TempSensor))) return 0;
#elif defined(STM32F0)
if(!(Channel & ADC_Channel_TempSensor)) return 0;
#endif
ushort dat = 1;
int n = 0;
for(int i=0; i<ArrayLength(ADC_Pins); i++, dat <<= 1)
{
if(Channel & dat) n++;
}
return Data[n];
}
ushort ADConverter::ReadVrefint()
{
// 先判断有没有打开通道
#if defined(STM32F1) || defined(GD32)
if(!(Channel & (1 << ADC_Channel_Vrefint))) return 0;
#elif defined(STM32F0)
if(!(Channel & ADC_Channel_Vrefint)) return 0;
#endif
ushort dat = 1;
int n = 0;
for(int i=0; i<ArrayLength(ADC_Pins); i++, dat <<= 1)
{
if(Channel & dat) n++;
}
#if defined(STM32F1) || defined(GD32)
if(Channel & (1 << ADC_Channel_TempSensor)) n++;
#elif defined(STM32F0)
if(Channel & ADC_Channel_TempSensor) n++;
#endif
return Data[n];
}
#if defined(STM32F0) && !defined(GD32)
ushort ADConverter::ReadVbat()
{
// 先判断有没有打开通道
if(!(Channel & ADC_Channel_Vbat)) return 0;
ushort dat = 1;
int n = 0;
for(int i=0; i<ArrayLength(ADC_Pins); i++, dat <<= 1)
{
if(Channel & dat) n++;
}
if(Channel & ADC_Channel_TempSensor) n++;
if(Channel & ADC_Channel_Vrefint) n++;
return Data[n];
}
#endif

View File

@ -17,20 +17,18 @@ STM32F103内部ADC
Port
*/
class ADConverter //: public AnalogPort //有两个通道不在引脚上 不用继承的好
class ADConverter
{
private:
void* _ADC; // 当前中断线的引用
Pin _Pins[16];
AnalogInPort _ports[16];
byte _PinCount;
public :
byte Line; // 中断线 1/2/3
byte Count; // 通道个数
uint Channel; // 使用哪些通道,每个通道一位
#ifdef STM32F1
ushort Data[18]; // 存放数据
#else
ushort Data[19]; // 存放数据
#endif
// 如果需要读取温度和电压通道需要设置0x30000
ADConverter(byte line = 1, uint channel = 0);
@ -41,8 +39,10 @@ public :
ushort Read(Pin pin);
ushort ReadTempSensor();
ushort ReadVrefint();
#if defined(STM32F0) && !defined(GD32)
ushort ReadVbat();
#endif
private:
void OnInit();
void OnOpen();
};
#endif

240
Platform/STM32F1/ADC.cpp Normal file
View File

@ -0,0 +1,240 @@
#include "ADC.h"
#include "Platform\stm32.h"
void ADConverter::OnInit()
{
ADC_TypeDef* const g_ADCs[]= ADCS;
_ADC = g_ADCs[Line - 1];
const Pin g_Pins1[] = ADC1_PINS;
const Pin g_Pins3[] = ADC3_PINS;
auto ps = Line == 1 ? g_Pins1 : g_Pins3;
_PinCount = Line == 1 ? ArrayLength(g_Pins1) : ArrayLength(g_Pins3);
for(int i=0; i<ArrayLength(_Pins) && i<_PinCount; i++)
{
_Pins[i] = ps[i];
}
}
void ADConverter::OnOpen()
{
auto at = (ADC_TypeDef*)_ADC;
/* Enable DMA clock */
#ifdef STM32F4
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
ADC_DeInit();
#else
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
ADC_DeInit(at);
#endif
/* Enable ADC and GPIOC clock */
//RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOC, ENABLE);
const int g_ADC_rccs[]= ADC_RCCS;
RCC_APB2PeriphClockCmd(g_ADC_rccs[Line - 1], ENABLE);
/* DMA channel1 configuration */
#ifdef STM32F4
DMA_DeInit(DMA1_Stream0);
DMA_InitTypeDef dma;
DMA_StructInit(&dma);
dma.DMA_PeripheralBaseAddr = (uint)&at->DR; //ADC地址
//dma.DMA_MemoryBaseAddr = (uint)&Data; //内存地址
//dma.DMA_DIR = DMA_DIR_PeripheralSRC;
dma.DMA_BufferSize = Count;
dma.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址固定
dma.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存地址固定
dma.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //半字
dma.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
dma.DMA_Mode = DMA_Mode_Circular; //循环传输
dma.DMA_Priority = DMA_Priority_High;
//dma.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Stream0, &dma);
/* Enable DMA channel1 */
DMA_Cmd(DMA1_Stream0, ENABLE);
#else
DMA_DeInit(DMA1_Channel1);
DMA_InitTypeDef dma;
DMA_StructInit(&dma);
dma.DMA_PeripheralBaseAddr = (uint)&at->DR; //ADC地址
dma.DMA_MemoryBaseAddr = (uint)&Data; //内存地址
dma.DMA_DIR = DMA_DIR_PeripheralSRC;
dma.DMA_BufferSize = Count;
dma.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址固定
dma.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存地址固定
dma.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //半字
dma.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
dma.DMA_Mode = DMA_Mode_Circular; //循环传输
dma.DMA_Priority = DMA_Priority_High;
dma.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel1, &dma);
/* Enable DMA channel1 */
DMA_Cmd(DMA1_Channel1, ENABLE);
#endif
/* ADC configuration */
ADC_InitTypeDef adc;
ADC_StructInit(&adc);
#if defined(STM32F1) || defined(GD32)
adc.ADC_Mode = ADC_Mode_Independent; //独立ADC模式
adc.ADC_ScanConvMode = ENABLE ; //禁止扫描模式,扫描模式用于多通道采集
adc.ADC_ContinuousConvMode = ENABLE; //开启连续转换模式即不停地进行ADC转换
adc.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //不使用外部触发转换
adc.ADC_DataAlign = ADC_DataAlign_Right; //采集数据右对齐
adc.ADC_NbrOfChannel = Count; //要转换的通道数目1
ADC_Init(at, &adc);
#if defined(GD32)
RCC_ADCCLKConfig(RCC_ADCCLK_APB2_DIV6);
#else
/*配置ADC时钟为PCLK2的8分频即9MHz*/
RCC_ADCCLKConfig(RCC_PCLK2_Div8);
#endif
/*配置ADC1的通道10 11为55. 5个采样周期序列为1 */
//ADC_RegularChannelConfig(at, ADC_Channel_10, 1, ADC_SampleTime_55Cycles5);
uint dat = 1;
uint n = 1;
for(byte i=0; i<ArrayLength(Data); i++, dat <<= 1)
{
if(Channel & dat)
{
// 第三个参数rank必须连续
if(i < ADC_Channel_TempSensor)
ADC_RegularChannelConfig(at, i, n++, ADC_SampleTime_55Cycles5);
else
ADC_RegularChannelConfig(at, i, n++, ADC_SampleTime_239Cycles5);
}
}
if(Channel & 0x30000) ADC_TempSensorVrefintCmd(ENABLE);
/* Enable ADC DMA */
ADC_DMACmd(at, ENABLE);
/* Enable ADC */
ADC_Cmd(at, ENABLE);
/*复位校准寄存器 */
ADC_ResetCalibration(at);
/*等待校准寄存器复位完成 */
while(ADC_GetResetCalibrationStatus(at));
/* ADC校准 */
ADC_StartCalibration(at);
/* 等待校准完成*/
while(ADC_GetCalibrationStatus(at));
/* 由于没有采用外部触发所以使用软件触发ADC转换 */
ADC_SoftwareStartConvCmd(at, ENABLE);
#elif defined(STM32F0)
/* ADC DMA request in circular mode */
ADC_DMARequestModeConfig(at, ADC_DMAMode_Circular);
/* Enable ADC_DMA */
ADC_DMACmd(at, ENABLE);
/* Configure the ADC in continous mode withe a resolutuion equal to 12 bits */
adc.ADC_Resolution = ADC_Resolution_12b;
adc.ADC_ContinuousConvMode = ENABLE;
adc.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
adc.ADC_DataAlign = ADC_DataAlign_Right;
adc.ADC_ScanDirection = ADC_ScanDirection_Backward;
ADC_Init(at, &adc);
dat = 1;
for(int i=0; i<ArrayLength(Data); i++, dat <<= 1)
{
if(Channel & dat)
{
ADC_ChannelConfig(at, dat , ADC_SampleTime_55_5Cycles);
if(dat == ADC_Channel_TempSensor)
ADC_TempSensorCmd(ENABLE);
else if(dat == ADC_Channel_Vrefint)
ADC_VrefintCmd(ENABLE);
else if(dat == ADC_Channel_Vbat)
ADC_VbatCmd(ENABLE);
}
}
/* ADC Calibration */
ADC_GetCalibrationFactor(at);
/* Enable ADC */
ADC_Cmd(at, ENABLE);
// GD32F130需要20us左右的延时
Sys.Delay(2000);
/* Wait the ADCEN falg */
while(!ADC_GetFlagStatus(at, ADC_FLAG_ADEN));
/* ADC regular Software Start Conv */
ADC_StartOfConversion(at);
#endif
}
ushort ADConverter::ReadTempSensor()
{
// 先判断有没有打开通道
#if defined(STM32F1) || defined(GD32)
if(!(Channel & (1 << ADC_Channel_TempSensor))) return 0;
#elif defined(STM32F0)
if(!(Channel & ADC_Channel_TempSensor)) return 0;
#endif
ushort dat = 1;
int n = 0;
for(int i=0; i<_PinCount; i++, dat <<= 1)
{
if(Channel & dat) n++;
}
return Data[n];
}
ushort ADConverter::ReadVrefint()
{
// 先判断有没有打开通道
#if defined(STM32F1) || defined(GD32)
if(!(Channel & (1 << ADC_Channel_Vrefint))) return 0;
#elif defined(STM32F0)
if(!(Channel & ADC_Channel_Vrefint)) return 0;
#endif
ushort dat = 1;
int n = 0;
for(int i=0; i<_PinCount; i++, dat <<= 1)
{
if(Channel & dat) n++;
}
#if defined(STM32F1) || defined(GD32)
if(Channel & (1 << ADC_Channel_TempSensor)) n++;
#elif defined(STM32F0)
if(Channel & ADC_Channel_TempSensor) n++;
#endif
return Data[n];
}
#if defined(STM32F0) && !defined(GD32)
ushort ADConverter::ReadVbat()
{
// 先判断有没有打开通道
if(!(Channel & ADC_Channel_Vbat)) return 0;
ushort dat = 1;
int n = 0;
for(int i=0; i<_PinCount; i++, dat <<= 1)
{
if(Channel & dat) n++;
}
if(Channel & ADC_Channel_TempSensor) n++;
if(Channel & ADC_Channel_Vrefint) n++;
return Data[n];
}
#endif