stm32 用TIM2实现外部脉冲计数,串口无法输出

2019-03-23 16:50发布

    设计思路:stm32 用TIM2实现外部脉冲计数,按键4充当外部脉冲。预期实验现象:LED3灭,串口输出脉冲个数(即按下的按键次数),延时,LED3亮,延时,LED3灭,输出脉冲个数,如此循环。
   问题:真实现象是LED3闪一下就再也不亮了,串口没有任何输出。是我串口设置的问题吗?请各位大神指教。拜托。
   程序如下:

/*脉冲量测量*/
#include "stm32f10x.h"
#include <stdio.h>
void delay(uint32_t);
void RCC_Configuration(void);
void GPIO_Configuration(void);
void TIM2_Configuration(void);
void COM_DMA_Config(void);
void LED_Config(void);
int fputc(int ch, FILE *f);
int fgetc( FILE *f);
uint8_t buff[5200];
uint32_t count=0;


int main(void)
{
        RCC_Configuration();
    GPIO_Configuration();
    TIM2_Configuration();
        COM_DMA_Config() ;
        LED_Config() ;   

    while (1)
    {
          delay(6000000);
          GPIO_SetBits(GPIOD,GPIO_Pin_4);       
          printf("计数=%dr/min ", count);
          delay(6000000);
          GPIO_ResetBits(GPIOD,GPIO_Pin_4);
    }   
}



void RCC_Configuration(void)
{
    SystemInit();
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD,ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 , ENABLE);
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
}

void LED_Config(void)
{
           GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;          
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;       
    GPIO_Init(GPIOD, &GPIO_InitStructure);

        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;          
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;       
    GPIO_Init(GPIOD, &GPIO_InitStructure);
}

//外部脉冲输入管脚
void GPIO_Configuration(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;           //TIM2_CH1
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;       
    GPIO_Init(GPIOA, &GPIO_InitStructure);


}
void  TIM2_Configuration(void)
{
    DMA_InitTypeDef  DMA_InitStructure;
        TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
        DMA_DeInit(DMA1_Channel5);
        /*外设地址为TIM2的CNT(计数器寄存器)*/
        DMA_InitStructure.DMA_PeripheralBaseAddr= (u32)&TIM2->CNT;
        /*内存地址*/
        DMA_InitStructure.DMA_MemoryBaseAddr=(u32)&count;
        /*外设至内存模式*/
        DMA_InitStructure.DMA_DIR=DMA_DIR_PeripheralSRC;
        DMA_InitStructure.DMA_BufferSize=1;
        /*外设地址不自动加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;
        DMA_Init(DMA1_Channel5,&DMA_InitStructure);
        DMA_Cmd(DMA1_Channel5, ENABLE);



  TIM_DeInit(TIM2);
  TIM_TimeBaseStructure.TIM_Period = 0xFFFF;      //?自动重装载值,值越小频率越大,值越大频率越小
  TIM_TimeBaseStructure.TIM_Prescaler = 0x0;      
  TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;  
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数模式

  TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure);      
  TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0);          //外部时钟模式2,计数器在选定输入端的每个上升沿计数
  TIM_SetCounter(TIM2, 0);           //设置寄存器寄存值
  TIM_Cmd(TIM2, ENABLE);
  TIM_DMACmd(TIM2,TIM_DMA_COM,ENABLE);                 //TIM_DMA_Update: TIM update Interrupt source
                                             //TIM_DMA_CC1: TIM Capture Compare 1 DMA source
                                             //TIM_DMA_CC2: TIM Capture Compare 2 DMA source
                                             //TIM_DMA_CC3: TIM Capture Compare 3 DMA source
                                             //TIM_DMA_CC4: TIM Capture Compare 4 DMA source
                                             //TIM_DMA_COM: TIM Commutation DMA source
                                             //TIM_DMA_Trigger: TIM Trigger DMA source

}

void COM_Config(void)
{
    GPIO_InitTypeDef  GPIO_InitStructure;
        USART_InitTypeDef USART_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD|RCC_APB2Periph_AFIO, ENABLE);          
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);          
       
        /*设置TX*/
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 ;   
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;                  
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                  
    GPIO_Init(GPIOD, &GPIO_InitStructure);
        /*设置RX*/
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 ;   
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;                  
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                  
    GPIO_Init(GPIOD, &GPIO_InitStructure);
        /*重映射*/
        GPIO_PinRemapConfig(GPIO_Remap_USART2,ENABLE);

   USART_InitStructure.USART_BaudRate=115200;
   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_Init(USART1,&USART_InitStructure);
   USART_Cmd(USART2,ENABLE);
}

//用DMA将脉冲数转至内存
void COM_DMA_Config(void)
{
                   DMA_InitTypeDef DMA_InitStructure;

        /*使能DMA时钟*/
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);       
       
        /*设置DMA传输的外设地址*/
        DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&USART2->DR;  
       
        /*设置DMA传输内存地址(要传输的变量的指针)*/
        DMA_InitStructure.DMA_MemoryBaseAddr = (u32)buff;
       
        /*DMA传输方向:从内存到外设*/       
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
       
        /*DMA传输的数据量*/
        DMA_InitStructure.DMA_BufferSize = 5200;  

        /*外设地址不增*/
        DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
       
        /*内存地址递增*/
        DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;

        /*外设数据单位 8位*/
        DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;  
       
        /*内存数据单位 8位*/
        DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
       
        /*DMA模式:一次传输*/
        DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;  //工作在正常缓存模式
       
        /*优先级:中*/
        DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; //DMA通道 x拥有中优先级
       
        /*禁止内存到内存的传输        */
        DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;  //DMA通道x没有设置为内存到内存传输

        /*配置DMA1的17通道*/       
        DMA_Init(DMA1_Channel7, &DMA_InitStructure);  //根据DMA_InitStruct中指定的参数初始化DMA的通道USART1_Tx_DMA_Channel所标识的寄存器
       
        DMA_Cmd(DMA1_Channel7, ENABLE);  //使能USART1 TX DMA1 所指示的通道           
}





#ifndef MicroLIB
//#pragma import(__use_no_semihosting)             //没有实现fgetc时需要声明该参数   
/* 标准库需要的支持函数 使用printf()调试打印不需要实现该函数 */               
struct __FILE
{
        int handle;
    /* Whatever you require here. If the only file you are using is */   
    /* standard output using printf() for debugging, no file handling */   
    /* is required. */
};

FILE __stdout;      
//定义_sys_exit()以避免使用半主机模式   
_sys_exit(int x)
{
        x = x;
}
/* 重定义fputc函数 如果使用MicroLIB只需要重定义fputc函数即可 */  
int fputc(int ch, FILE *f)
{
    /* Place your implementation of fputc here */

         /* e.g. write a character to the USART */
    USART_SendData(USART2, (uint8_t) ch);

    /* Loop until the end of transmission */
    while (USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET)
    {}

    return ch;
}
/*
可以直接使用putchar
不需要再定义 int putchar(int ch),因为stdio.h中有如下定义
#define putchar(c) putc(c, stdout)
*/

int ferror(FILE *f) {  
    /* Your implementation of ferror */  
    return EOF;  
}
#endif

FILE __stdin;

int fgetc(FILE *fp)
{
        int ch = 0;
       
    while(USART_GetFlagStatus(USART2, USART_FLAG_RXNE) == RESET)
    {
    }

    ch = (int)USART2->DR & 0xFF;
       
    putchar(ch); //回显
       
        return ch;
}

void delay(__IO uint32_t nCount)
{
    for (; nCount != 0; nCount--);
}




此帖出自小平头技术问答
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。