思路是这样子的,用ADC1进行四通道采样,并利用DMA存入数组StatusData[4]中去,之后采样完成后进入ADC1的中断对数据进行处理,之后再在主函数中将数据显示出来。
现在的问题是仿真之后是可以进入中断的,但是好像就是无法检测到采样的值??
***********************************************************************************************
*
* SampleDriver.c
*
------------------------------------------------------------------------------------------------
File Name: SampleDriver.c
Description: 按键的驱动程序。
Interface: void SampleInit(void) 显示系统初始化函数
void ValueDisplay(unsigned char Tube, 显示数值函数
unsigned int Value,
unsigned char Digi)
void LEDControl(unsigned char Group, 控制LED
unsigned int Data)
------------------------------------------------------------------------------------------------
Create: 2009.01.11 by Ross Li
Modify:
***********************************************************************************************/
#include "DISPLAYER.h"
#include "SampleDriver.h"
#include "stm32f10x.h"
#include "sys.h"
#include "delay.h"
#define SAMPLE_TIMES 50 //数字平滑滤波的采样数
#define ADC1_DR_Address ((u32)0x40012400+0x4c)
//__IO uint16_t ADC_ConvertedValue;
unsigned long StatusData[4]; //存放采样值的数组
uint32_t Current[SAMPLE_TIMES], CurrFB; //存放反馈电流采样数据的数组和变量,用于数字平滑滤波
uint32_t Voltage[SAMPLE_TIMES], VolFB; //存放反馈电压采样数据的数组和变量,用于数字平滑滤波
uint32_t CurrentSet[SAMPLE_TIMES], Curr; //存放给定电流采样数据的数组和变量,用于数字平滑滤波
uint32_t VoltageSet[SAMPLE_TIMES], Vol; //存放给定电压采样数据的数组和变量,用于数字平滑滤波
/***********************************************************************************************
* void SampleInit(void)
* 用来初始化显示系统硬件,包括SPI总线的初始化和显示刷新信号CLK的初始化,显示刷新信号用
* PWM0信号来实现。
------------------------------------------------------------------------------------------------
Para: void
Return: void
***********************************************************************************************/
void SampleInit(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
ADC_InitTypeDef ADC_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_GPIOC|RCC_APB2Periph_ADC1 , ENABLE ); //使能ADC1通道时钟
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
RCC_ADCCLKConfig(RCC_PCLK2_Div6); //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M
//PA0、PA1 作为模拟通道输入引脚
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模拟输入引脚
GPIO_Init(GPIOA, &GPIO_InitStructure);
//PC2、PC3 作为模拟通道输入引脚
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模拟输入引脚
GPIO_Init(GPIOC, &GPIO_InitStructure);
ADC_DeInit(ADC1); //复位ADC1
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //ADC工作模式:ADC1和ADC2工作在独立模式
ADC_InitStructure.ADC_ScanConvMode = ENABLE; //模数转换工作在单通道模式
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; //模数转换工作在单次转换模式
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //转换由软件而不是外部触发启动
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //ADC数据右对齐
ADC_InitStructure.ADC_NbrOfChannel = 4; //顺序进行规则转换的ADC通道的数目
ADC_Init(ADC1, &ADC_InitStructure); //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器
/*配置ADC1的通道0为55. 5个采样周期,序列为1 */
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);
/*配置ADC1的通道1为55. 5个采样周期,序列为2 */
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_55Cycles5);
/*配置ADC1的通道12为55. 5个采样周期,序列为3 */
ADC_RegularChannelConfig(ADC1, ADC_Channel_12, 3, ADC_SampleTime_55Cycles5);
/*配置ADC1的通道13为55. 5个采样周期,序列为4 */
ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 4, ADC_SampleTime_55Cycles5);
DMA_DeInit(DMA1_Channel1);
DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address; //ADC地址
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&StatusData;//内存地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = 8; //DMA通道的DMA缓存的大小
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设地址固定
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存地址寄存器递增
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //半字,数据宽度为16位
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //循环传输
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //DMA通道x没有设置为内存到内存传输
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
DMA_Cmd(DMA1_Channel1, ENABLE);//使能DMA1
ADC_Cmd(ADC1, ENABLE); //使能指定的ADC1
ADC_ResetCalibration(ADC1); //使能复位校准
while(ADC_GetResetCalibrationStatus(ADC1)); //等待复位校准结束
ADC_StartCalibration(ADC1); //开启AD校准
while(ADC_GetCalibrationStatus(ADC1)); //等待校准结束
ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能指定的ADC1的软件转换启动功能
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_InitStructure.NVIC_IRQChannel = ADC1_2_IRQn; //ADC1,ADC2全局中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;//先占优先级0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //从优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
ADC_ITConfig(ADC1,ADC_IT_EOC,ENABLE);
}
/***********************************************************************************************
* uint32_t GetVoltageSet(void)
* 返回给定电压的实际值
*
------------------------------------------------------------------------------------------------
Para: void
Return: INT32U 给定电压的实际值,格式为xx.x V
***********************************************************************************************/
uint32_t GetVoltageSet(void){
uint32_t Voltage;
if( Mode )
Voltage = Vol ;
//Voltage = 80 + Vol * 300 / 1023;
else
Voltage = 15 + Vol * 60 / 1023;
return( Voltage );
}
/***********************************************************************************************
* INT32U GetCurrentSet(void)
* 返回给定电流的实际值
*
------------------------------------------------------------------------------------------------
Para: void
Return: INT32U 给定电流的实际值,格式为xxx A
***********************************************************************************************/
uint32_t GetCurrentSet(void){ //电流给定
uint32_t Current;
uint32_t Current_MIN;
if (AllPara.Dia == 0){
Current = 40 + ( Vol * 25/82 -20 ) * 180/235 ;
Current_MIN = 40;
}
else if (AllPara.Dia == 1){
Current = 60 + ( Vol * 25/82 -20 ) * 200/235 ;
Current_MIN = 60;
}
else if (AllPara.Dia == 2){
Current = 80 + ( Vol * 25/82 -20 ) * 220/235 ;
Current_MIN = 80;
}
else if (AllPara.Dia == 3){
Current = 80 + ( Vol * 25/82 -20 ) * 320/235 ;
Current_MIN = 80;
}
else if (AllPara.Dia == 4){
Current = 80 + ( Vol * 25/82 -20 ) * 420/235 ;
Current_MIN = 80;
}
if((Vol * 25/82)<20)
Current = Current_MIN;
//Current = 40 + Curr * 300 / 1023; 原始
return( Current );
}
/**********************************************************************************************
* INT32U GetVoltage(void)
* 返回反馈电压的实际值
*
-----------------------------------------------------------------------------------------------
Para: void
Return: INT32U 反馈电压的实际值,格式为xx.x V
**********************************************************************************************/
uint32_t GetVoltage(void){
uint32_t Voltage;
Voltage = VolFB * 600 / 1023;
return( Voltage );
}
/**********************************************************************************************
* INT32U GetCurrent(void)
* 返回反馈电流的实际值
*
-----------------------------------------------------------------------------------------------
Para: void
Return: INT32U 反馈电流的实际值,格式为xxx A
**********************************************************************************************/
uint32_t GetCurrent(void){
uint32_t Current;
Current = CurrFB * 600 / 1023;
return( Current );
}
//ADC中断服务程序
void ADC1_2_IRQHandler(void)
{
static uint32_t Sum[4]; //用于记录当前记录区间的采样值总和
static uint8_t Times; //用于记录采样次数的变量
// ADCSequenceDataGet(ADC_BASE, 1, StatusData); //读取采样数据
/* 进行平滑滤波 */
Current[Times] = StatusData[0]; //平滑滤波算法:求取最近N次采样的平均...
Voltage[Times] = StatusData[1]; //...值作为采样值
CurrentSet[Times] = StatusData[2];
VoltageSet[Times] = StatusData[3];
if( SAMPLE_TIMES == ++Times )
Times = 0;
Sum[0] += StatusData[0]; //计算最近N个采样周期采样值的总和
Sum[1] += StatusData[1]; //算法:上次的总和加上最新的采样值...
Sum[2] += StatusData[2]; //...再减去保留的最早的采样值
Sum[3] += StatusData[3];
Sum[0] -= Current[Times];
Sum[1] -= Voltage[Times];
Sum[2] -= CurrentSet[Times];
Sum[3] -= VoltageSet[Times];
CurrFB = Sum[0] / SAMPLE_TIMES; //求取最近N个采样周期采样值的平均值
VolFB = Sum[1] / SAMPLE_TIMES;
Curr = Sum[2] / SAMPLE_TIMES;
Vol = Sum[3] / SAMPLE_TIMES;
ADC_ClearITPendingBit(ADC1, ADC_IT_EOC);
}
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
一周热门 更多>