用stm32f103实现频率计设计。使用2个通用定时器,一个计时,另一个对外部信号计数,在LCD上显示出计数值和频率值。并且将代码展示出来
时间: 2024-02-19 14:01:38 浏览: 34
好的,我会为您提供一份基于STM32F103的频率计的设计方案及代码示例。
首先,我们需要使用2个通用定时器,一个用于计时,另一个用于对外部信号计数。我们可以将TIM2用于计时,TIM3用于计数。
接下来,我们需要在STM32F103上搭建一个LCD,用于显示计数值和频率值。这里我们选择使用1602A LCD模块。
最后,我们需要编写代码,实现计时、计数和LCD显示功能。下面是代码示例:
```
#include "stm32f10x.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_tim.h"
#include "stm32f10x_usart.h"
#define TIM2_PERIOD 65535
#define TIM3_PERIOD 65535
uint16_t TIM2_Overflow = 0;
uint16_t TIM3_Counter = 0;
uint16_t TIM3_Capture = 0;
uint32_t TIM3_Frequency = 0;
void TIM2_Configuration(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
TIM_TimeBaseStructure.TIM_Period = TIM2_PERIOD;
TIM_TimeBaseStructure.TIM_Prescaler = 71;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
TIM_Cmd(TIM2, ENABLE);
}
void TIM3_Configuration(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_ICInitTypeDef TIM_ICInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
TIM_TimeBaseStructure.TIM_Period = TIM3_PERIOD;
TIM_TimeBaseStructure.TIM_Prescaler = 71;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_ICInitStructure.TIM_ICFilter = 0x0;
TIM_ICInit(TIM3, &TIM_ICInitStructure);
TIM_ITConfig(TIM3, TIM_IT_Update | TIM_IT_CC1, ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
TIM_Cmd(TIM3, ENABLE);
}
void LCD_Configuration(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_SetBits(GPIOA, GPIO_Pin_8);
GPIO_SetBits(GPIOA, GPIO_Pin_9);
GPIO_SetBits(GPIOB, GPIO_Pin_0);
GPIO_ResetBits(GPIOB, GPIO_Pin_1);
GPIO_ResetBits(GPIOB, GPIO_Pin_2);
GPIO_ResetBits(GPIOB, GPIO_Pin_3);
GPIO_ResetBits(GPIOB, GPIO_Pin_4);
GPIO_ResetBits(GPIOB, GPIO_Pin_5);
}
void LCD_WriteCommand(uint8_t c)
{
GPIO_ResetBits(GPIOA, GPIO_Pin_8);
GPIO_ResetBits(GPIOB, GPIO_Pin_0);
GPIO_Write(GPIOB, (c & 0xF0));
GPIO_SetBits(GPIOA, GPIO_Pin_9);
GPIO_ResetBits(GPIOA, GPIO_Pin_9);
GPIO_Write(GPIOB, (c << 4));
GPIO_SetBits(GPIOA, GPIO_Pin_9);
GPIO_ResetBits(GPIOA, GPIO_Pin_9);
TIM_Delay(2);
}
void LCD_WriteData(uint8_t c)
{
GPIO_SetBits(GPIOA, GPIO_Pin_8);
GPIO_ResetBits(GPIOB, GPIO_Pin_0);
GPIO_Write(GPIOB, (c & 0xF0));
GPIO_SetBits(GPIOA, GPIO_Pin_9);
GPIO_ResetBits(GPIOA, GPIO_Pin_9);
GPIO_Write(GPIOB, (c << 4));
GPIO_SetBits(GPIOA, GPIO_Pin_9);
GPIO_ResetBits(GPIOA, GPIO_Pin_9);
TIM_Delay(2);
}
void LCD_SetCursor(uint8_t x, uint8_t y)
{
uint8_t address = y * 0x40 + x;
address |= 0x80;
LCD_WriteCommand(address);
}
void LCD_WriteString(uint8_t *s)
{
while (*s)
{
LCD_WriteData(*s++);
}
}
void TIM_Delay(uint32_t t)
{
TIM2_Overflow = 0;
TIM_Cmd(TIM2, ENABLE);
while (TIM2_Overflow < t);
TIM_Cmd(TIM2, DISABLE);
}
void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
TIM2_Overflow++;
}
}
void TIM3_IRQHandler(void)
{
if (TIM_GetITStatus(TIM3, TIM_IT_CC1) != RESET)
{
TIM_ClearITPendingBit(TIM3, TIM_IT_CC1);
TIM3_Capture = TIM_GetCapture1(TIM3);
TIM3_Frequency = SystemCoreClock / (TIM3_Capture + TIM3_Counter * TIM3_PERIOD);
TIM3_Counter = 0;
}
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
TIM3_Counter++;
}
}
int main(void)
{
TIM2_Configuration();
TIM3_Configuration();
LCD_Configuration();
while (1)
{
char lcd_buffer[16];
LCD_SetCursor(0, 0);
sprintf(lcd_buffer, "Count: %d", TIM3_Capture);
LCD_WriteString(lcd_buffer);
LCD_SetCursor(0, 1);
sprintf(lcd_buffer, "Freq: %d Hz", TIM3_Frequency);
LCD_WriteString(lcd_buffer);
TIM_Delay(500);
}
}
```
这份代码实现了计时、计数和LCD显示功能。在主函数中,我们通过调用`TIM_Delay()`函数来等待一段时间,然后更新LCD显示内容。在`TIM3_IRQHandler()`函数中,我们通过捕获外部信号的上升沿来计数,然后根据计数值计算频率。