1、我使用定时器输出比较模式中的timing模式,进行周期定时,并产生中断,但是时间不准确
2、ADC串口输出通道之间发生错位
望高人指点,下面是我的程序
#include "stm32f10x.h"
#include "stm32f10x_it.h"
#include "UART_INTERFACE.h"
#include "SysTickDelay.h"
#include "EVAL.h"
#include <stdio.h>
volatile bool ShiJianDao=FALSE;
#define N 10 //每通道采10次
#define M 3 //为3个通道
vu16 AD_Value[N][M];
vu16 After_filter[M];
int i;
int j=0;
uint16_t PrescalerValue = 0;
__IO uint16_t CCR2_Val = 10000;
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/*GPIOA Configuration: TIM3 channel2*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; //TIM_CH2
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Configure USART1 Tx (PA.09) as alternate function push-pull */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Configure USART1 Rx (PA.10) as input floating */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//PA0/1/2 作为模拟通道输入引脚
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模拟输入引脚
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* Configure the NVIC Preemption Priority Bits */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); //设置优先级分组:先占优先级1位,从优先级3位
#ifdef VECT_TAB_RAM
/* Set the Vector Table base location at 0x20000000 */
NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0); //向量表位于RAM
#else /* VECT_TAB_FLASH */
/* Set the Vector Table base location at 0x08000000 */
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0); //向量表位于FLASH
#endif
/* Enable the TIM3 gloabal Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
//配置系统时钟,使能各外设时钟
void RCC_Configuration(void)
{
ErrorStatus HSEStartUpStatus;
RCC_DeInit(); //RCC system reset(for debug purpose)
RCC_HSEConfig(RCC_HSE_ON); //Enable HSE
HSEStartUpStatus = RCC_WaitForHSEStartUp(); //Wait till HSE is ready
if(HSEStartUpStatus == SUCCESS)
{
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); //Enable Prefetch Buffer
FLASH_SetLatency(FLASH_Latency_2); //Set 2 Latency cycles
RCC_HCLKConfig(RCC_SYSCLK_Div1); //AHB clock = SYSCLK
RCC_PCLK2Config(RCC_HCLK_Div1); //APB2 clock = HCLK
RCC_PCLK1Config(RCC_HCLK_Div4); //APB1 clock = HCLK/4
RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_6); //PLLCLK = 12MHz * 6 = 72 MHz
RCC_PLLCmd(ENABLE); //Enable PLL
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET); //Wait till PLL is ready
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); //Select PLL as system clock source
while(RCC_GetSYSCLKSource() != 0x08); //Wait till PLL is used as system clock source
RCC_ADCCLKConfig(RCC_PCLK2_Div6); //72M/6=12,ADC最大时间不能超过14M
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //使能DMA传输
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO
| RCC_APB2Periph_USART1 |RCC_APB2Periph_ADC1 , ENABLE); //使能GPIO外设和AFIO复用功能模块时钟使能
}
}
void TIM3_Configuration(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
PrescalerValue = (uint16_t) (36000000 / 2000) - 1;
/* ---------------------------------------------------------------
TIM3CLK 36MHz
TIM3 Configuration: generate 1 signals :
TIM3CLK = 36 MHz, Prescaler = 0x0, TIM3 counter clock = 549.3Hz
--------------------------------------------------------------- */
/* Time base configuration */
TIM_TimeBaseStructure.TIM_Period = 65535;
TIM_TimeBaseStructure.TIM_Prescaler =0;
TIM_TimeBaseStructure.TIM_ClockDivision= 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
TIM_PrescalerConfig(TIM2, PrescalerValue, TIM_PSCReloadMode_Immediate);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Timing;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = CCR2_Val;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC2Init(TIM3, &TIM_OCInitStructure);
//失能 TIMx 在 CCR1 上的预装载寄存器
TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Disable);
TIM_ITConfig(TIM3, TIM_IT_CC2 , ENABLE);
/* TIM3 enable counter */
TIM_Cmd(TIM3, ENABLE); //使能TIMx外设
}
void ADC1_Configuration(void)
{
ADC_InitTypeDef ADC_InitStructure;
/* Resets ADC1 */
ADC_DeInit(ADC1); //将外设 ADC1 的全部寄存器重设为缺省值
/* ADC1 configuration ------------------------------------------------------*/
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //ADC工作模式:ADC1和ADC2工作在独立模式
ADC_InitStructure.ADC_ScanConvMode =ENABLE; //模数转换工作在扫描模式
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE ; //模数转换工作在连续转换模式
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //ADC数据右对齐
ADC_InitStructure.ADC_NbrOfChannel = M; //顺序进行规则转换的ADC通道的数目
ADC_Init(ADC1, &ADC_InitStructure); //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器
//设置指定ADC的规则组通道,设置它们的转化顺序和采样时间
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5 ); //ADC1,ADC通道2,规则采样顺序值为3,采样时间为55.5周期
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_55Cycles5 );
ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 3, ADC_SampleTime_55Cycles5 );
/* Enable ADC1 */
ADC_Cmd(ADC1, ENABLE); //使能指定的ADC1
// 开启ADC的DMA支持(要实现DMA功能,还需独立配置DMA通道参等数)
/* Enable ADC1 reset calibaration register */
ADC_ResetCalibration(ADC1); //重置指定的ADC1的校准寄存器
/* Check the end of ADC1 reset calibration register */
while(ADC_GetResetCalibrationStatus(ADC1)); //获取ADC1重置校准寄存器的状态,设置状态则等待
/* Start ADC1 calibaration */
ADC_StartCalibration(ADC1); //开始指定ADC1的校准状态
/* Check the end of ADC1 calibration */
while(ADC_GetCalibrationStatus(ADC1)); //获取指定ADC1的校准程序,设置状态则等待
}
void DMA_Configuration(void)
{
/* ADC1 DMA1 Channel Config */
DMA_InitTypeDef DMA_InitStructure;
DMA_DeInit(DMA1_Channel1); //将DMA的通道1寄存器重设为缺省值
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&ADC1->DR; //DMA外设ADC基地址
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&AD_Value; //DMA内存基地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //内存作为数据传输的目的地
DMA_InitStructure.DMA_BufferSize = M*N; //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; //数据宽度为16位
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //工作在正常模式
DMA_InitStructure.DMA_Priority = DMA_Priority_High; //DMA通道 x拥有高优先级
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //DMA通道x没有设置为内存到内存传输
DMA_Init(DMA1_Channel1, &DMA_InitStructure); //根据DMA_InitStruct中指定的参数初始化DMA的通道
/* DMA IT enable */
//DMA_ITConfig(DMA_Channel1, DMA_IT_TC, ENABLE); //使能DMA传输完成中断
}
//配置所有外设
void Init_All_Periph(void)
{
RCC_Configuration();
NVIC_Configuration();
GPIO_Configuration();
TIM3_Configuration();
ADC1_Configuration();
DMA_Configuration();
//USART1_Configuration();
USART_Configuration(9600);
// USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
// USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
}
u16 GetVolt(u16 advalue)
{
return (u16)(advalue * 330 / 4096);
}
void filter(void)
{
int sum = 0;
u8 count;
for(i=0;i<M;i++)
{
for ( count=0;count<N;count++)
{
sum += AD_Value[count]
;
}
After_filter=sum/N;
sum=0;
}
}
int main(void)
{
u16 value[M];
Init_All_Periph();
SysTick_Initaize();
while(1)
{
if(ShiJianDao==TRUE)
{
delay_us(9);
ADC_SoftwareStartConvCmd(ADC1, DISABLE);
ADC_DMACmd(ADC1, DISABLE);
DMA_Cmd(DMA1_Channel1, DISABLE);
ShiJianDao=FALSE;
}
if(j==10)
{
filter();
delay_ms(6);
for(i=0;i<M;i++)
{
value=GetVolt(After_filter);
printf("value[%d]: %d.%dv
",i,value/100,value%100) ;
}
j=0;
}
}
}
中断函数
uint16_t capture = 0;
extern __IO uint16_t CCR2_Val;
extern volatile bool ShiJianDao;
extern int j;
void TIM3_IRQHandler(void)
{
if (TIM_GetITStatus(TIM3, TIM_IT_CC2) != RESET)
{
TIM_ClearITPendingBit(TIM3, TIM_IT_CC2);
capture = TIM_GetCapture2(TIM3); //获得 TIM3 输入捕获 2的值
TIM_SetCompare2(TIM3, capture + CCR2_Val); //设置 TIM3 捕获比较 2寄存器值
ADC_DMACmd(ADC1, ENABLE);
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
DMA_Cmd(DMA1_Channel1, ENABLE); //启动DMA通道
printf("please wait!
");
ShiJianDao=TRUE;
j++;
}
}
此帖出自小平头技术问答
一周热门 更多>