5

我正在研究 STM32 F103x 上的 ADC 编程,并从最简单的情况开始——单次转换。内部温度传感器(连接到 ADC1)值被测量并使用 USART 将其发送到 COM 端口。目标似乎很清楚,但是当我尝试将源代码下载到闪存时,它不会向 COM 端口发送任何数据。USART 功能运行良好,我猜问题出在 ADC 配置部分,因为我被挂在等待完成转换的循环中:

while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET); //Wail for conversion complete

到目前为止,这是我的源代码。

/* Includes ------------------------------------------------------------*/
#include "stm32f10x.h"
#include <stdio.h>

    uint16_t AD_value;
    const uint16_t V25 = 1750; //when V25=1.41V
    const uint16_t Avg_Slope = 5; //when avg_slc
    uint16_t TemperatureC;

//Define output device
PUTCHAR_PROTOTYPE
{
    USART_SendData(USART1, (uint8_t) ch);
    while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET)
    {}
    return ch;
}

void Usart1Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);

    /* COnfig PA9 for USART Tx 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);

    /* COnfig PA10 for USART Rx as input floating */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    /* USARTx configured as follow:
        - BaudRate = 9600 baud  
        - Word Length = 8 Bits
        - One Stop Bit
        - No parity
        - Hardware flow control disabled (RTS and CTS signals)
        - Receive and transmit enabled
    */  
    USART_InitStructure.USART_BaudRate = 9600;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_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;

    /* USART configuration */
    USART_Init(USART1, &USART_InitStructure);
    USART_Cmd(USART1, ENABLE);  

}

int main(void)
{

    ADC_InitTypeDef ADC_InitStructure;
    Usart1Init();

    RCC_ADCCLKConfig(RCC_PCLK2_Div6); //ADCCLK = PCLK22/6 = 72/6=12MHz
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); //Enable ADC1 Clock

    /* ADC1 configuration */
    ADC_DeInit(ADC1); //Power-on default
    ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //Independent conversion mode (single)
    ADC_InitStructure.ADC_ScanConvMode = DISABLE; //Convert single channel only
    ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //Convert 1 time
    ADC_InitStructure.ADC_ExternalTrigConv = DISABLE; //No external triggering
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //Right 12-bit data alignment
    ADC_InitStructure.ADC_NbrOfChannel = 1; //single channel conversion
    ADC_Init(ADC1, &ADC_InitStructure);
    ADC_TempSensorVrefintCmd(ENABLE); //wake up temperature sensor
    ADC_Cmd(ADC1, ENABLE); //Enable ADC1
    ADC_ResetCalibration(ADC1); //Enable ADC1 reset calibration register
    while(ADC_GetResetCalibrationStatus(ADC1)); //check the end of ADC1 reset calibration register  
    ADC_StartCalibration(ADC1); //Start ADC1 calibration
    while(ADC_GetCalibrationStatus(ADC1)); //Check the end of ADC1 calibration
    ADC_RegularChannelConfig(ADC1, ADC_Channel_16, 1, ADC_SampleTime_1Cycles5); //Select 1.5 cycles conversion for channel 16
    ADC_SoftwareStartConvCmd(ADC1, ENABLE); //Start ADC1 software conversion
    while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET); //Wail for conversion complete
    AD_value = ADC_GetConversionValue(ADC1); //Read ADC value
    ADC_ClearFlag(ADC1, ADC_FLAG_EOC); //Clear EOC flag

    printf("\r\n ADC value: %d \r\n", AD_value);
    TemperatureC = (uint16_t)((V25-AD_value)/Avg_Slope+25);
    printf("Temperature: %d%cC\r\n", TemperatureC, 176);
    while (1)
    {}  
}

任何想法表示赞赏!

4

3 回答 3

6

我将尝试解释源代码发生了什么。

1-禁用的定义为零:typedef enum {DISABLE = 0, ENABLE = !DISABLE} FunctionalState;

2-所以当你写“ADC_InitStructure.ADC_ExternalTrigConv = DISABLE;” 您实际上将其分配为零,例如“ADC_InitStructure.ADC_ExternalTrigConv = 0;

3-这意味着您将 ADC_CR2 寄存器的 EXTSEL 分配为零。

4-如果 EXTSEL 为零,则 adc 转换取决于定时器启动。

5-如果要软件启动adc,EXTSEL必须为0x000E0000;

6-你可以猜到“ADC_ExternalTrigConv_None”的值被定义为0x000E0000;

所以同时(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)== RESET);代码会挂在这里,因为它依赖于定时器来启动,如果没有启动它就无法结束。

于 2016-08-08T14:11:53.543 回答
4

问题解决了!禁用外部触发器是我的错。而不是使用:

ADC_InitStructure.ADC_ExternalTrigConv = DISABLE;

它应该是这样的:

ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;

多么愚蠢!

于 2015-02-04T11:18:18.860 回答
0

I will not invent a wheel here by saing that you are hanging in one of those three while() loops. Make some output before each of then then you will know where you are hanging.

If you have debugger (it is present on every ST development board, and possibly you are using it to download program) don't hesitate to use it :)

于 2015-02-04T08:15:11.707 回答