初级会员

- 积分
- 85
- 金钱
- 85
- 注册时间
- 2015-8-21
- 在线时间
- 13 小时
|
5金钱
想用STM32做ADC采集,然后用DMA发到串口在电脑上显示出来,但是发现通过计算进行的ADC配置和实际效果不相符
我用的是ADC1 ADC时钟频率12M 然后采样周期选的是55.5 用了DMA中断,去采集1Khz的PWM波,每次采200个点
按照手册里的计算 TCONV = 采样时间+ 12.5个周期 一次采样的时间为200*(1/12M)*(55.5+12.5)=1.13ms 差不多该是PWM波的一周期多,但是我把数组拉出来后发现这两个点差不多包含了有8个PWM波周期了...
不清楚是不是配置哪里出问题了还是DMA没用好,希望大神们指点下。
[mw_shl_code=c,true]//*************************************************************************
// 函数名 :GPIO_Configuration
// 描述 :引脚配置
// 入口 :
// 出口 :
// 返回 :
//*************************************************************************
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD |RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB
|RCC_APB2Periph_AFIO |RCC_APB2Periph_ADC1|RCC_APB2Periph_GPIOC ,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART5, ENABLE); //使能串口5时钟
RCC_ADCCLKConfig(RCC_PCLK2_Div6); //配置低速ADC时钟等于SYSCLK/6 12M
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; //管脚12
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(GPIOC, &GPIO_InitStructure); //TX5初始化
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //管脚2
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
GPIO_Init(GPIOD, &GPIO_InitStructure); //RX5初始化
GPIO_PinRemapConfig(GPIO_PartialRemap2_TIM2, ENABLE); //Timer2部分重映射 TIM2_CH3-> B10
//设置该引脚为复用输出功能,输出TIM2 CH3的PWM脉冲波形 GPIOB.10
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //TIM2_CH3
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIO
//PB1 作为模拟通道9输入引脚 CP输入
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
//*************************************************************************
// 函数名 :ADC_Init1
// 描述 :ADC初始化 ADC1 ch9 PB1
// 入口 :
// 出口 :
// 返回 :
//*************************************************************************
void ADC_Init1(void)
{
ADC_InitTypeDef ADC_InitStructure;//ADC初始化结构体声明
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //独立的转换模式 对应双模式
ADC_InitStructure.ADC_ScanConvMode = DISABLE; //关闭扫描模式
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; //开启连续转换模式
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//ADC外部开关,SWSTART
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//对齐方式,ADC为12位中,右对齐方式
ADC_InitStructure.ADC_NbrOfChannel = 1;//开启通道数,1个
ADC_Init(ADC1, &ADC_InitStructure);
ADC_RegularChannelConfig(ADC1, ADC_Channel_9, 1, ADC_SampleTime_55Cycles5);//ADC通道组, 第9个通道 采样顺序1
ADC_DMACmd(ADC1, ENABLE); //使能ADC1和DMA的链接
ADC_Cmd(ADC1, ENABLE); //使能ADC1
ADC_ResetCalibration(ADC1); //重新校准
while(ADC_GetResetCalibrationStatus(ADC1));//等待重新校准完成
ADC_StartCalibration(ADC1);//开始校准
while(ADC_GetCalibrationStatus(ADC1));//等待校准完成
ADC_SoftwareStartConvCmd(ADC1, ENABLE); //连续转换开始,ADC通过DMA方式不断的更新RAM区。
}
//*************************************************************************
// 函数名 :DMA_Init1
// 描述 :DMA初始化
// 入口 :
// 出口 :
// 返回 :
//*************************************************************************
void DMA_Init1(void)
{
DMA_InitTypeDef DMA_InitStructure; //DMA初始化结构体声明
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); // 使能 DMA 时钟
DMA_DeInit(DMA1_Channel1); //开启DMA1第一通道
DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address; //DMA对应的外设基地址
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADC_ConvertedValue; //内存存储基地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //DMA的转换模式为SRC模式,由外设搬移到内存
DMA_InitStructure.DMA_BufferSize = USART_REC_LEN; //DMA缓存大小,120个,单位为DMA_MemoryDataSize
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搬数据尺寸,HalfWord就是为16位
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //转换模式,非循环缓存模式。
DMA_InitStructure.DMA_Priority = DMA_Priority_High; //DMA优先级高
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //M2M模式禁用
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
DMA_ClearFlag(DMA1_FLAG_TC1);
DMA_ITConfig( DMA1_Channel1, DMA1_IT_TC1, ENABLE ); //开通道传输完成标志
DMA_Cmd(DMA1_Channel1, DISABLE); //使能DMA1通道1
}
//*************************************************************************
// 函数名 :UART_Init
// 描述 :串口初始化
// 入口 :
// 出口 :
// 返回 :
//*************************************************************************
void UART_Init(void)
{
USART_InitTypeDef USART_InitStructure; //串口初始化结构体声明
USART_InitStructure.USART_BaudRate = 9600; //波特率9600
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //字长8位
USART_InitStructure.USART_StopBits = USART_StopBits_1; //1位停止字节
USART_InitStructure.USART_Parity = USART_Parity_No; //无奇偶校验
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //打开Rx接收和Tx发送功能
USART_Init(UART5, &USART_InitStructure);
USART_Cmd(UART5, ENABLE);
USART_ClearFlag(UART5,USART_FLAG_RXNE);
USART_ITConfig(UART5, USART_IT_RXNE, DISABLE);
}
//*************************************************************************
// 函数名 :NVIC_Configuration
// 描述 :中断配置
// 入口 :
// 出口 :
// 返回 :
//*************************************************************************
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* Configure the NVIC Preemption Priority Bits */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
/* Enable the USART5 Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = UART5_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* Enable the DMA1 Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn; //DMA通道1中断允许
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
//*************************************************************************
// 函数名 :TIM3_Configuration
// 描述 :定时器3初始化
// 入口 :
// 出口 :
// 返回 :
//*************************************************************************
void TIM3_Configuration (void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能
TIM_TimeBaseStructure.TIM_Period = 49; //自动装载的计数值 计数从0开始所以50-1
TIM_TimeBaseStructure.TIM_Prescaler = 7199; //预分频系数,为0时表示不分频 所以 7200-1 Time时钟为10K
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//计数模式
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
TIM_ARRPreloadConfig(TIM3, ENABLE); //自动重装允许
TIM_ClearFlag(TIM3, TIM_FLAG_Update); //清除溢出中断
TIM_ITConfig( TIM3, TIM_IT_Update, ENABLE); //允许定时器3中断
//中断优先级NVIC设置
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级0级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //从优先级3级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
NVIC_Init(&NVIC_InitStructure); //初始化NVIC寄存器
TIM_Cmd(TIM3, ENABLE); //使能TIMx
/*******************************************************************************
* Function Name : DMA1_Channel1_IRQHandler
* Description : This function handles DMA1 Channel 1 interrupt request.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void DMA1_Channel1_IRQHandler(void)
{
DMA1->IFCR = DMA1_IT_GL1;//清除通道全局中断标志
//ADC_Oversampled_Data = Oversampling_GetConversion(); //得到过采样结果
DMA1_Channel1->CCR &= 0xFFFFFFFE;//关闭DMA通道
DMA1_Channel1->CNDTR = USART_REC_LEN; //重新配置DMA 数目 地址
DMA1_Channel1->CMAR = (u32)ADC_ConvertedValue;
ADC_DMA_STA=1;
//处理得到数据
TIM_Cmd(TIM3, DISABLE); //关闭定时器
// }
}
} [/mw_shl_code]
|
|