社区导航

 

搜索
查看: 1744|回复: 9

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

[复制链接]

53

TA的帖子

0

TA的资源

一粒金砂(中级)

Rank: 2

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

/*脉冲量测量*/
#include "stm32f10x.h"
#include
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 \n\r", 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--);
}




此帖出自stm32/stm8论坛

回复

使用道具 举报

3578

TA的帖子

0

TA的资源

版主

Rank: 6Rank: 6

发表于 2018-1-4 15:00 | 显示全部楼层
太长了

点评

或者不看程序,请问,TIM可以对松开、按下按键产生的脉冲计数吗?涉及到TIM哪部分的设置,只需要设置ETR管脚,还是需要设置输入捕获?  详情 回复 发表于 2018-1-4 15:37

回复

使用道具 举报

53

TA的帖子

0

TA的资源

一粒金砂(中级)

Rank: 2

 楼主| 发表于 2018-1-4 15:32 | 显示全部楼层

拜托大神耐心看一下,它看着长一部分是因为我的注释太多,拜托拜托

回复

使用道具 举报

53

TA的帖子

0

TA的资源

一粒金砂(中级)

Rank: 2

 楼主| 发表于 2018-1-4 15:37 | 显示全部楼层

或者不看程序,请问,TIM可以对松开、按下按键产生的脉冲计数吗?涉及到TIM哪部分的设置,只需要设置ETR管脚,还是需要设置输入捕获?

回复

使用道具 举报

3658

TA的帖子

11

TA的资源

五彩晶圆(高级)

Rank: 9Rank: 9Rank: 9

发表于 2018-1-4 17:26 | 显示全部楼层
把串口输出。部分屏蔽掉。看看灯的运行状态。若正常。就检查串口配置方面,可以看看例程的初始化和调用。

点评

好的,请问,TIM可以对松开、按下按键产生的脉冲计数吗?涉及到TIM哪部分的设置,只需要设置ETR管脚,还是需要设置输入捕获?  详情 回复 发表于 2018-1-4 17:33

回复

使用道具 举报

53

TA的帖子

0

TA的资源

一粒金砂(中级)

Rank: 2

 楼主| 发表于 2018-1-4 17:33 | 显示全部楼层
ienglgge 发表于 2018-1-4 17:26
把串口输出。部分屏蔽掉。看看灯的运行状态。若正常。就检查串口配置方面,可以看看例程的初始化和调用。

好的,请问,TIM可以对松开、按下按键产生的脉冲计数吗?涉及到TIM哪部分的设置,只需要设置ETR管脚,还是需要设置输入捕获?

点评

可以,就是输入捕获功能  详情 回复 发表于 2018-1-4 17:48

回复

使用道具 举报

1万

TA的帖子

15

TA的资源

版主

Rank: 6Rank: 6

发表于 2018-1-4 17:48 | 显示全部楼层
本帖最后由 ddllxxrr 于 2018-1-4 17:50 编辑
shrxh 发表于 2018-1-4 17:33
好的,请问,TIM可以对松开、按下按键产生的脉冲计数吗?涉及到TIM哪部分的设置,只需要设置ETR管脚,还 ...

可以,就是定义定时器 输入捕获功能,及相应的通道。

点评

问题已解决,谢谢  详情 回复 发表于 2018-1-4 20:58
http://shop34182318.taobao.com/
https://shop436095304.taobao.com/?spm=a230r.7195193.1997079397.37.69fe60dfT705yr

回复

使用道具 举报

395

TA的帖子

0

TA的资源

纯净的硅(中级)

Rank: 5Rank: 5

发表于 2018-1-4 20:39 | 显示全部楼层
你就没调用串口初始化的函数,你只调用串口DMA初始化的函数了,个人感觉,串口作为调试口打印调试信息时,没有大量数据要发送,没必要使用DMA,那样纯粹是给自己找麻烦。写程序一定要仔细,该调用什么函数一定要清楚

点评

嗯嗯,知道啦。  详情 回复 发表于 2018-1-7 21:36

回复

使用道具 举报

53

TA的帖子

0

TA的资源

一粒金砂(中级)

Rank: 2

 楼主| 发表于 2018-1-4 20:58 | 显示全部楼层
ddllxxrr 发表于 2018-1-4 17:48
可以,就是定义定时器 输入捕获功能,及相应的通道。

问题已解决,谢谢

回复

使用道具 举报

53

TA的帖子

0

TA的资源

一粒金砂(中级)

Rank: 2

 楼主| 发表于 2018-1-7 21:36 | 显示全部楼层
wudayongnb 发表于 2018-1-4 20:39
你就没调用串口初始化的函数,你只调用串口DMA初始化的函数了,个人感觉,串口作为调试口打印调试信息时, ...

嗯嗯,知道啦。

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

关闭

站长推荐上一条 1/4 下一条

  • 论坛活动 E手掌握

    扫码关注
    EEWORLD 官方微信

  • EE福利  唾手可得

    扫码关注
    EE福利 唾手可得

Archiver|手机版|小黑屋|电子工程世界 ( 京ICP证 060456 )

GMT+8, 2020-4-5 23:12 , Processed in 0.284787 second(s), 19 queries , Gzip On, MemCache On.

快速回复 返回顶部 返回列表