本帖最后由 Tenant_2013 于 2013-4-22 22:42 编辑
这是一个测试程序,完成后将在毕业设计的组内共享,各人添加、修改,完善成自己的程序,所以3路采样只用了2路。恭请各位大神帮忙看看问题。
型号:STM32F103RBT6;功能:ADC采样3路信号,通过DMA送入Memory;经过main函数的计算,再通过DMA送入TIM的CCR寄存器,产生2路PWM。
调整ADC输入,通过WatchWindow观察到ADC采样跟随变化,没有问题。
但DMA没有将TIM1_CCR1_Address (0x40012C34)和TIM1_CCR2_Address (0x40012C38)更新,它们始终保持以初始占空比(75%、37.5%)输出PWM。
main.c如下:
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
/* Private define ------------------------------------------------------------*/
/* Average Length */
#define N 10
/* Registers Address */
/* From "Memory Map" in "STM32F103x8 STM32F103xB Datasheet" & "TIM Registers" in "RM0008 Reference Manual";
Registers Address = Sector Address + Offset Address */
/* ADC1: DR (Regular Data Register) Address */
#define ADC1_DR_Address ((uint32_t)0x4001244C) /* 0x 4001 2400 + 0x 4C */
/* TIM1: CCR1, CCR2 (Conpare/Capture Register) Address */
#define TIM1_CCR1_Address ((uint32_t)0x40012C34) /* 0x 4001 2C00 + 0x 34 */
#define TIM1_CCR2_Address ((uint32_t)0x40012C38) /* 0x 4001 2C00 + 0x 38 */
/* Private variables ---------------------------------------------------------*/
uint16_t TimerPeriod; /* PWM Period */
volatile uint16_t i, u, t; /* Current, Voltage, Temperature */
/* Define Buffers */
uint16_t ADC_ConvertedValueTab[4*N];
uint16_t TIM1_CH1_PulseWidth;
uint16_t TIM1_CH2_PulseWidth;
/* Private function prototypes -----------------------------------------------*/
/* Clock Function */
void RCC_Configuration(void);
/* Peripheral Functions */
void GPIO_Configuration(void);
void DMA_Configuration(void);
void ADC_Configuration(void);
void TIM_Configuration(void);
/* Average Function */
uint16_t Average(char c);
/* Private functions ---------------------------------------------------------*/
int main(void)
{
/*!< At this stage the microcontroller clock setting is already configured,
this is done through SystemInit() function which is called from startup
file (startup_stm32f10x_xx.s) before to branch to application main.
To reconfigure the default setting of SystemInit() function, refer to
system_stm32f10x.c file
*/
/*
C/C++ / Define: USE_STDPERIPH_DRIVER,STM32F10X_MD
startup_stm32f10x_md.s: SystemInit()
system_stm32f10x.c: #define SYSCLK_FREQ_72MHz 72000000
PLLMUL: PLLCLK = 8MHz * 9 = 72 MHz
SW: SYSCLK = PLLCLK = 72 MHz
AHB Prescaler: HCLK = SYSCLK = 72 MHz
APB2 Prescaler: PCLK2 = HCLK/1 = 72 MHz
APB1 Prescaler: PCLK1 = HCLK/2 = 36 MHz
}
*/
/* System Clocks Configuration */
RCC_Configuration();
/* GPIO Configuration */
GPIO_Configuration();
/* DMA Configuration */
DMA_Configuration();
/* ADC configuration */
ADC_Configuration();
/* TIM Configuration */
TIM_Configuration();
while (1)
{
i = Average('i'); /* Current Sampling*/
u = Average('u'); /* Voltage Sampling */
t = Average('t'); /* Temperature Sampling */
TIM1_CH1_PulseWidth = i;
TIM1_CH2_PulseWidth = t;
}
}
void RCC_Configuration(void)
{
/* Set ADC Prescaler, ADCCLK = PCLK2/6 = 12 MHz */
RCC_ADCCLKConfig(RCC_PCLK2_Div6);
/* Enable DMA1 clock */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
/* Enable ADC1, ADC2, TIM1, GPIOA and GPIOC clocks */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_ADC2 | RCC_APB2Periph_TIM1 | RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC, ENABLE);
}
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure; /* Define GPIO_InitStructure */
/* GPIOA Configuration */
/* PA.08 (AF,PP) - TIM1_CH1; PA.09 (AF,PP) - TIM1_CH2 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9; /* Select GPIO Pins */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; /* Alternate Function & Push-Pull*/
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; /* GPIO Speed = 50MHz */
GPIO_Init(GPIOA, &GPIO_InitStructure); /* Configure GPIOA */
/* GPIOC Configuration */
/* PC.02 (AIN) - ADC_12; PC.03 (AIN) - ADC_13; PC.04 (AIN) - ADC_14 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4; /* Select GPIO Pins */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; /* Analog Input */
GPIO_Init(GPIOC, &GPIO_InitStructure); /* Configure GPIOC */
}
void DMA_Configuration(void)
{
DMA_InitTypeDef DMA_InitStructure; /* Define DMA_InitStructure */
/* DMA1 channel1 Configuration: DMA1_Channel1 - ADC1_Channel12 & ADC1_Channel13 --------*/
DMA_DeInit(DMA1_Channel1);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC1_DR_Address; /* Peripheral Base Address */
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ADC_ConvertedValueTab; /* Memory Base Address */
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; /* From Peripheral To Memory */
DMA_InitStructure.DMA_BufferSize = N*2; /* Buffer Size: 2N */
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; /* Peripheral Increase: Disable */
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; /* Memory Increase: Enable */
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word; /* Peripheral Data Size: 32 bits */
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word; /* Memory Data Size: 32 bits */
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; /* Circular */
DMA_InitStructure.DMA_Priority = DMA_Priority_High; /* Priority: High */
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; /* Memory To Memory: Disable */
/* Initialize DMA1_Channel1 */
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
/* Enable DMA1_Channel1 */
DMA_Cmd(DMA1_Channel1, ENABLE);
/* DMA1 Channel2 Configuration: DMA1_Channel2 - TIM1_Channel1) */
DMA_DeInit(DMA1_Channel2);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)TIM1_CCR1_Address; /* Peripheral Base Address */
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&TIM1_CH1_PulseWidth; /* Memory Base Address */
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; /* From Memory To Peripheral */
DMA_InitStructure.DMA_BufferSize = 1; /* Memory Buffer Size: 1 */
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; /* Peripheral Increase: Disable */
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; /* Memory Increase: Disable */
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; /* Peripheral Data Size: 16 bits */
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; /* Memory Data Size: 16 bits */
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; /* Circular */
DMA_InitStructure.DMA_Priority = DMA_Priority_High; /* Priority: High */
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; /* Memory To Memory: Disable */
/* Initialize DMA1_Channel2 */
DMA_Init(DMA1_Channel2, &DMA_InitStructure);
/* Enable DMA1_Channel2 */
DMA_Cmd(DMA1_Channel2, ENABLE);
/* DMA1 Channel3 Configuration: DMA1_Channel3 - TIM1_Channel2) */
DMA_DeInit(DMA1_Channel3);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)TIM1_CCR2_Address;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&TIM1_CH2_PulseWidth;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_BufferSize = 1;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
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;
/* DMA1 Channel3 Initialization */
DMA_Init(DMA1_Channel3, &DMA_InitStructure);
/* DMA1 Channel3 enable */
DMA_Cmd(DMA1_Channel3, ENABLE);
}
void ADC_Configuration(void)
{
ADC_InitTypeDef ADC_InitStructure;
/* ADC1 Configuration ------------------------------------------------------*/
ADC_InitStructure.ADC_Mode = ADC_Mode_RegSimult; /* ADC1 & ADC2: dual */
ADC_InitStructure.ADC_ScanConvMode = ENABLE; /* Scan */
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; /* Continuous */
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; /* No External Trigger */
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; /* Right Alignment */
ADC_InitStructure.ADC_NbrOfChannel = 2; /* Number of Channels: 2 */
ADC_Init(ADC1, &ADC_InitStructure); /* Configure ADC1 */
/* ADC1 regular channels configuration; ADC1: ADC_CH12, Sequence: 1; Sample Time: 28.5 Cycles */
ADC_RegularChannelConfig(ADC1, ADC_Channel_12, 1, ADC_SampleTime_28Cycles5);
/* ADC1 regular channels configuration; ADC1: ADC_CH13, Sequence: 2; Sample Time: 28.5 Cycles */
ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 2, ADC_SampleTime_28Cycles5);
/* Enable The DMA Function of ADC1 */
ADC_DMACmd(ADC1, ENABLE);
/* ADC2 Configuration ------------------------------------------------------*/
ADC_InitStructure.ADC_Mode = ADC_Mode_RegSimult;
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_InitStructure.ADC_NbrOfChannel = 2;
ADC_Init(ADC2, &ADC_InitStructure);
/* ADC2 regular channels configuration; ADC2: ADC_CH14, Sequence: 1; Sample Time: 28.5 Cycles */
ADC_RegularChannelConfig(ADC2, ADC_Channel_14, 1, ADC_SampleTime_28Cycles5);
/* ADC2 regular channels configuration; ADC2: ADC_CH14, Sequence: 2; Sample Time: 28.5 Cycles */
ADC_RegularChannelConfig(ADC2, ADC_Channel_14, 2, ADC_SampleTime_28Cycles5);
/* ADC1: Enable & Calibration */
/* Enable ADC1 */
ADC_Cmd(ADC1, ENABLE);
/* Enable ADC1 reset calibration register */
ADC_ResetCalibration(ADC1);
/* Check the end of ADC1 reset calibration register */
while(ADC_GetResetCalibrationStatus(ADC1));
/* Start ADC1 calibration */
ADC_StartCalibration(ADC1);
/* Check the end of ADC1 calibration */
while(ADC_GetCalibrationStatus(ADC1));
/* ADC2: Enable & Calibration */
/* Enable ADC2 */
ADC_Cmd(ADC2, ENABLE);
/* Enable ADC2 reset calibration register */
ADC_ResetCalibration(ADC2);
/* Check the end of ADC2 reset calibration register */
while(ADC_GetResetCalibrationStatus(ADC2));
/* Start ADC2 calibration */
ADC_StartCalibration(ADC2);
/* Check the end of ADC2 calibration */
while(ADC_GetCalibrationStatus(ADC2));
/* Start ADC1, ADC2 */
/* Start ADC1 Software Conversion */
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
/* Start ADC2 Software Conversion */
ADC_SoftwareStartConvCmd(ADC2, ENABLE);
}
void TIM_Configuration(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
/* TIM1 Configuration ---------------------------------------------------
Generate 2 PWM signals with 2 different duty cycles:
TIM1CLK = SystemCoreClock, Prescaler = 0, TIM1 counter clock = SystemCoreClock
- Prescaler = (TIM1CLK / TIM1 counter clock) - 1 = 0.
SystemCoreClock is set to 72 MHz for Medium-density device.
The TIM1 is running at 50 KHz:
TIM1 Frequency = TIM1 counter clock / (ARR + 1) = 72 MHz / 1440 = 50 KHz
The objective is to generate 2 PWM signal at 50 KHz:
- TIM1_Period = (SystemCoreClock / 50000) - 1
The channel 1 duty cycle is set to 75%
The channel 2 duty cycle is set to 37.5%
The Timer pulse is calculated as follows:
- ChannelxPulse = DutyCycle * (TIM1_Period - 1) / 100
----------------------------------------------------------------------- */
/* Compute ARR value (PWM Wave Pulse Width) to generate signal frequency at 50000 KHz */
TimerPeriod = (SystemCoreClock / 50000 ) - 1;
/* Initialize CCR1 value (Channel1 Pulse Width) at 75% duty cycle for channel 1 */
TIM1_CH1_PulseWidth = (uint16_t) (((uint32_t) 75 * (TimerPeriod - 1)) / 100);
/* Initialize CCR2 value (Channel2 Pulse Width) at 37.5% duty cycle for channel 2 */
TIM1_CH2_PulseWidth = (uint16_t) (((uint32_t) 375 * (TimerPeriod - 1)) / 1000);
/* Time Base configuration (Timer Counting Configuration) */
TIM_TimeBaseStructure.TIM_Prescaler = 0; /* Prescaler = 0 */
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; /* Count Up */
TIM_TimeBaseStructure.TIM_Period = TimerPeriod; /* ARR */
TIM_TimeBaseStructure.TIM_ClockDivision = 0; /* Clock Division = 0 */
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; /* UEV Configuration: Update st every Overflow */
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); /* Configure TIM1 */
/* Channel 1 and 2 Configuration in PWM mode (Channel Output Configuration) */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; /* PWM1 Mode (CNT < CCRx, High Level Output)*/
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; /* Positive Channel: Enable */
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable; /* Negative Channel: Disable */
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; /* Positive Channel Output: Low */
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_Low; /* Negative Channel Output: High */
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset; /* Positive Channel Idle Band: Reset */
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset; /* Negative Channel Idle Band: Reset */
TIM_OCInitStructure.TIM_Pulse = TIM1_CH1_PulseWidth; /* Channel1 Pulse Width */
TIM_OC1Init(TIM1, &TIM_OCInitStructure); /* Configure TIM1_CH1 */
TIM_OCInitStructure.TIM_Pulse = TIM1_CH2_PulseWidth; /* Channel2 Pulse Width */
TIM_OC2Init(TIM1, &TIM_OCInitStructure); /* Configure TIM1_CH2 */
/* Enable TIM1 Update DMA Request */
TIM_DMACmd(TIM1, TIM_DMA_Update, ENABLE);
/* Enable TIM1 Counter */
TIM_Cmd(TIM1, ENABLE);
/* Enable TIM1 Main Output */
TIM_CtrlPWMOutputs(TIM1, ENABLE);
}
/* Average: remove max, min; calculate the average. */
uint16_t Average(char c)
{
uint16_t j, max, min, sum, average, inc, num;
__IO uint16_t *a = ADC_ConvertedValueTab;
switch (c)
{
case 'i': num=N; inc=4; break;
case 'u': num=N; inc=4; a+=2; break;
case 't': num=N*2; inc=2; a+=1; break;
}
max = *a;
min = *a;
sum = 0;
for(j = 0; j < num; a+= inc, j++)
{
if(*a > max) max = *a;
if(*a < min) min = *a;
sum+= *a;
}
average = (sum-max-min)/(num-2);
return average;
}
/************************END OF FILE***********************/
先谢谢各路大神! |
|