【Stm32杂谈】:Stm32F103野火指南针开发板红外遥控程序问题记录和解析(个人理解)


                                        

 

项目场景:

        最近在使用Stm32F103野火指南针开发板开发红外遥控外设得时候,用得是野火得开发板,本来发现应该很简单的事情,官方也很贴切的提供了官方例程。但是居然有问题,无法正常使用

        于是这篇文章应运而生,以下是个人心得,希望对大家有所帮助。


问题描述

        我确定自己下载的也没问题的情况下,居然无法使用,这让我又百思不得其解,左右翻看电子原理图引脚无问题,再看程序左右查询发现无问题,这让我怀疑是不是硬件问题。

        首先我用手机摄像头查看自己的遥控器是不是有问题,遥控器闪烁可以正常发送红外信号。

                                      

        单片机方面因为无有示波器,所以只能只用万用表,查看每次红外信号是否有电压变化,查看是有电压变化,0.3V左右,明显硬件无问题,很有可能就是程序问题,但是官方例程怎么会有问题呢!这让我百思不得其解!最后我还是相信自己,仔细去查看每个部分。

        官方例程下载链接:

                野火【红外遥控_1838】模块 — 野火产品资料下载中心 文档 (embedfire.com)


解决方案:

        左右对比程序,无任何问题,那就开始查询电路问题,翻看原理图。

 PE5端脚  与  程序定义无冲突。

这就很让人奇怪了,这时候我拿出了万用表将板载的PE5和红外的PE5是否互相连通,这时候发现居然没有互相连通,明显电路图的引脚就有问题了,于是挨个测引脚,最后发现红外接口与板载的PD12互相连通,于是修改程序中的引脚配置,完美解决问题。

官方下载链接,大家需要自行下载:

                野火STM32F103指南者开发板 — 野火产品资料下载中心 文档 (embedfire.com)

实物连接图:

              

修改程序如下(大家可以自己下载官方程序进行对比):

bsp_irda.c

/**
  ******************************************************************************
  * @file    bsp_irda.c
  * @author  fire
  * @version V1.0
  * @date    2013-xx-xx
  * @brief   红外遥控器接口
  ******************************************************************************
  * @attention
  *
  * 实验平台:野火 F103-指南者 STM32 开发板 
  * 论坛    :http://www.firebbs.cn
  * 淘宝    :https://fire-stm32.taobao.com
  *
  ******************************************************************************
  */
#include "stdio.h"
#include "./IrDa/bsp_irda.h" 
#include "./systick/bsp_SysTick.h"
#include "./led/bsp_led.h"

uint32_t frame_data=0;    /* 一帧数据缓存 */
uint8_t  frame_cnt=0;
uint8_t  frame_flag=0;    /* 一帧数据接收完成标志 */

 /**
  * @brief  配置嵌套向量中断控制器NVIC
  * @param  无
  * @retval 无
  */
static void NVIC_Configuration(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;
  
  /* Configure one bit for preemption priority */
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
  
  /* 配置P[A|B|C|D|E]11为中断源 */
  NVIC_InitStructure.NVIC_IRQChannel = IRDA_EXTI_IRQN;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 5;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
}

 
/* 初始化红外接收头1838用到的IO */
void IrDa_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure; 
	EXTI_InitTypeDef EXTI_InitStructure;

	/* config the extiline clock and AFIO clock */
	RCC_APB2PeriphClockCmd(IRDA_GPIO_CLK | RCC_APB2Periph_AFIO,ENABLE);
												
	/* config the NVIC */
	NVIC_Configuration();

	/* EXTI line gpio config */	
  GPIO_InitStructure.GPIO_Pin = IRDA_GPIO_PIN;       
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;	 
  GPIO_Init(IRDA_GPIO_PORT, &GPIO_InitStructure);

	/* EXTI line mode config */
  GPIO_EXTILineConfig(IRDA_GPIO_PORT_SOURCE, IRDA_GPIO_PIN_SOURCE); 
  EXTI_InitStructure.EXTI_Line = IRDA_EXTI_LINE;
  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿中断
  EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  EXTI_Init(&EXTI_InitStructure); 
}

/* 获取高电平的时间 */
uint8_t Get_Pulse_Time(void)
{
  uint8_t time = 0;
  while( IrDa_DATA_IN() )
  {
    time ++;
    Delay_us(2);     // 延时 20us
    if(time == 250)
      return time;   // 超时溢出   
  }
  return time;
}

/*
 * 帧数据有4个字节,第一个字节是遥控的ID,第二个字节是第一个字节的反码
 * 第三个数据是遥控的真正的键值,第四个字节是第三个字节的反码
 */
uint8_t IrDa_Process(void)
{
  uint8_t first_byte, sec_byte, tir_byte, fou_byte;  
  
  first_byte = frame_data >> 24;
  sec_byte = (frame_data>>16) & 0xff;
  tir_byte = frame_data >> 8;
  fou_byte = frame_data;
  
  /* 记得清标志位 */
  frame_flag = 0;
  
  if( (first_byte==(uint8_t)~sec_byte) && (first_byte==IRDA_ID) )
  {
    if( tir_byte == (u8)~fou_byte )
      return tir_byte;
  }
  
  return 0;   /* 错误返回 */
}

/*********************************************END OF FILE**********************/

bsp_irda.h

#ifndef __IRDA_H
#define	__IRDA_H

#include "stm32f10x.h"
void EXTI_PB11_Config(void);
void IrDa_Init(void);
uint8_t Get_Pulse_Time(void);
uint8_t IrDa_Process(void);

extern uint8_t  frame_flag;    /* 一帧数据接收完成标志 */


#define IRDA_ID 0

//红外遥控使用的GPIO及时钟
#define IRDA_GPIO_PORT    						GPIOD			              
#define IRDA_GPIO_CLK 	    					RCC_APB2Periph_GPIOD	
#define IRDA_GPIO_PIN									GPIO_Pin_12			        
#define IRDA_GPIO_PORT_SOURCE				GPIO_PortSourceGPIOD
#define IRDA_GPIO_PIN_SOURCE					GPIO_PinSource12

//中断相关
#define IRDA_EXTI_LINE								EXTI_Line12
#define IRDA_EXTI_IRQN								EXTI15_10_IRQn
#define IRDA_EXTI_IRQHANDLER_FUN			EXTI15_10_IRQHandler

 //读取引脚的电平
#define  IrDa_DATA_IN()	   GPIO_ReadInputDataBit(IRDA_GPIO_PORT,IRDA_GPIO_PIN)

#endif /* __IRDA_H */

项目链接:https://pan.baidu.com/s/1M_RLo5Q43f050p0Lkf1xTQ 


总结

        此处特此声明,没有任何黑野火官方的想法,实事求是我遇到的问题和板子的问题,不黑不吹,实际体验感受,希望大家不要在知识的海洋迷路。

        有问题可直接私信,如要打赏一块钱即可。


你的选择是做或不做,但不做就永远不会有机会。

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,针对您的问题,我来给您讲解如何在野火指南开发板上实现这个秒表程序野火指南开发板是基于STM32F103RCT6芯片设计的,因此我们可以使用与前面代码类似的方法在开发板上实现这个程序。下面是大致的步骤: 1. 硬件连接 将开发板的LCD屏幕连接到相应的引脚上。野火指南开发板的LCD屏幕接口与标准的HD44780接口不同,需要使用特定的库文件进行操作。具体的接线方式可以参考野火指南开发板的官方文档。 2. 创建工程 在Keil5中创建一个新工程,选择适用于STM32F103芯片的模板,然后进行一些基本的配置,如设置系统时钟等。 3. 编写程序 根据前面的代码,在main函数中添加如下代码: ``` int main(void) { // 初始化系统时钟,定时器和GPIO等相关硬件 RCC_Configuration(); GPIO_Configuration(); TIM_Configuration(); // 启动定时器 TIM_Cmd(TIM2, ENABLE); // 启用定时器中断 TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); // 启用全局中断 NVIC_EnableIRQ(TIM2_IRQn); while (1) {} } ``` 其中,RCC_Configuration()、GPIO_Configuration()和TIM_Configuration()是初始化系统时钟、GPIO和定时器的函数,需要根据具体的硬件和接口进行修改。启用定时器中断和全局中断的代码与前面的代码相同。 需要注意的是,野火指南开发板的定时器2默认使用的是APB1总线,因此需要将定时器时钟配置为APB1总线的2倍,即84MHz。具体的代码如下: ``` void TIM_Configuration(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; // 使能定时器2的时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); // 设置定时器2的参数 TIM_TimeBaseStructure.TIM_Period = 83999; // 定时器周期为1s TIM_TimeBaseStructure.TIM_Prescaler = 999; // 时钟分频系数为1000 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); // 清除定时器2的中断标志位 TIM_ClearITPendingBit(TIM2, TIM_IT_Update); } ``` 4. 编写LCD显示函数 野火指南开发板的LCD屏幕需要使用特定的库文件进行操作。在Keil5中,可以通过添加库文件的方式使用这些库函数。具体的使用方法可以参考野火指南开发板的官方文档。这里我们假设已经添加了相应的库文件,并编写了如下的LCD显示函数: ``` void LCD_ShowString(uint16_t x, uint16_t y, uint8_t *str) { uint16_t i = 0; while (str[i]) { LCD_ShowChar(x, y, str[i]); x += 8; i++; } } ``` 该函数可以在指定的位置显示一个字符串。需要注意的是,因为野火指南开发板的LCD屏幕分辨率较小,因此需要根据具体的情况调整字符串的位置和长度。 5. 定时器中断服务函数 野火指南开发板的定时器中断服务函数可以按照前面的代码进行编写。需要注意的是,在定时器中断服务函数中调用LCD显示函数时,需要根据具体的情况设置字符串的位置和长度。下面是一个简单的定时器中断服务函数示例: ``` void TIM2_IRQHandler(void) { if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) { // 清除定时器中断标志位 TIM_ClearITPendingBit(TIM2, TIM_IT_Update); // 计时器计数值加1 tick++; // 每1000次计数更新一次秒表 if (tick % 1000 == 0) { counter++; uint8_t str[16]; sprintf((char *)str, "%02d:%02d.%03d", counter / 60000, (counter % 60000) / 1000, counter % 1000); LCD_ShowString(0, 0, str); } } } ``` 6. 编译和下载程序 完成以上步骤后,可以编译程序并下载到野火指南开发板中。需要注意的是,下载程序之前需要将开发板连接到电脑上,并确保开发板的驱动程序已经正确安装。 希望这些步骤可以帮助您在野火指南开发板上实现这个秒表程序

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嵌入式up

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值