STM8 测量脉宽——红外例程

发布者:RadiantRiver最新更新时间:2018-07-24 来源: eefocus关键字:STM8  测量脉宽  红外例程 手机看文章 扫描二维码
随时随地手机看文章

实例说明:
1、本实例是利用STM8单片机定时器TIM1的PWM输入捕获模式测量红外遥控码。 2、红外遥控码格式为NEC红外编码。
3、红外接收信号输入接PC1(TIM1输入通道1)。
4、采用外部晶振16M。
5、采用IAR FOR STM8开发环境。
6、程序代码如下:
//--------------------------------------------------------------------
#i nclude  
#define uchar              unsigned char
#define uint                unsigned int 
uchar IrRecStep = 0;                             //接收步骤
uchar IrIndex = 0;                                //接收位数
uchar IrRecFlag = 0;                             //接收完标志
uchar IrRecBuff[4];                               //接收缓冲区
uchar IrRecAddr1;                                //红外地址码
uchar IrRecAddr2;
uchar IrRecData1;                                //红外数据码
uchar IrRecData2;
uint IrCycle = 0;                                  //红外周期
uint IrHigh = 0;                                   //占空比
const uchar IrCode[8]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; 
//--------引导码低电平范围------------------
#define IrHeadLow_Max       2300            //2300*4 = 9200us
#define IrHeadLow_Min        2100            //2100*4 = 8400us
//--------引导码高电平范围------------------
#define IrHeadHigh_Max      1250            //1250*4 = 5000us
#define IrHeadHigh_Min       1050            //1050*4 = 4200us
//--------数据0的周期范围-------------------
#define IrData00_Max         300             //300*4 = 1200us
#define IrData00_Min          260             //260*4 = 1040us
//--------数据1的周期范围-------------------
#define IrData10_Max         580             //580*4 = 2320us
#define IrData10_Min          540             //540*4 = 2160us
//--------数据0的占空比(高电平)范围---------
#define IrData0_Max          160             //160*4 = 640us
#define IrData0_Min           120             //120*4 = 480us
//--------数据1的占空比(高电平)范围---------
#define IrData1_Max          440             //440*4 = 1760us
#define IrData1_Min           400             //400*4 = 1600us
//----------------------------------------------------------
#define REMOTE_CLK_DIV       63              //63+1=64----16Mh/64=4us
#define REMOTE_ICF_FILTER   0x30 
//延时程序
void Delay_ms( uint ms )

  uint i,j;
  for( j=0; j   { 
    for( i=0; i<1000; i++ )
    {;} 
  }

//红外接收端口初始化
void Ir_Init(void)
{
  PC_DDR_DDR1 = 0;       //PC1为输入
  PC_CR1_C11 = 1;
  PC_CR2_C21 = 0;

//使用TIM1的PWM输入捕获
void Ir_PWM_Init(void)

  TIM1_PSCRH = 0;
  TIM1_PSCRL = REMOTE_CLK_DIV; 
  TIM1_CCER1 &= 0xee;//禁止输入捕获1,2
  TIM1_CCMR1 |= (REMOTE_ICF_FILTER + 0x01);// ch1到ti1fp1
  TIM1_CCER1 &= 0xec;//ch1 上升沿触发
  TIM1_CCMR2 |= (REMOTE_ICF_FILTER + 0x02);// ch2选择 ti1fp2上
  TIM1_CCER1 |= 0x20;//ch1 下降沿触发 ic2
  TIM1_SMCR |= 0x54;//选源触发源和触发方式 复位
  TIM1_CCER1 |= 0x11;//使能输入捕获1,2
  TIM1_CR1 |= 0x05;

//红外接收程序
void Ir_Receive(void)
{
  switch(IrRecStep)
  {
  case 0:
          IrIndex = 0;
          if ((TIM1_SR1_CC1IF == 1)&&(TIM1_SR1_CC2IF == 1))
          {
            IrHigh = (uint)(TIM1_CCR2H); 
            IrHigh = (IrHigh << 8) + TIM1_CCR2L;  //IrHigh占空比
            IrCycle = (uint)(TIM1_CCR1H);
            IrCycle = (IrCycle << 8) + TIM1_CCR1L;  //IrCycle周期
            //是否在引导码低电平范围内
            if (((IrCycle - IrHigh) < IrHeadLow_Max)&&((IrCycle - IrHigh) > IrHeadLow_Min))
            {
              IrRecStep = 1;
              TIM1_SR1_CC1IF = 0;
              TIM1_SR1_CC2IF = 0;
              TIM1_SR2_CC1OF = 0;
              TIM1_SR2_CC2OF = 0;
              TIM1_SR1_UIF = 0;
              
              IrRecBuff[0] = 0;
              IrRecBuff[1] = 0;
              IrRecBuff[2] = 0;
              IrRecBuff[3] = 0;
            }
          }
          break;
  case 1:
          if ((TIM1_SR2_CC1OF==1) || (TIM1_SR2_CC2OF==1) || (TIM1_SR1_UIF==1))
          { 
            IrRecStep = 0;
          }
          else
          { 
            if ((TIM1_SR1_CC1IF == 1)&&(TIM1_SR1_CC2IF == 1))
            { 
              IrHigh = (uint)(TIM1_CCR2H); 
              IrHigh = (IrHigh << 8) + TIM1_CCR2L;
              IrCycle = (uint)(TIM1_CCR1H); 
              IrCycle = (IrCycle << 8) + TIM1_CCR1L;
              //是否在引导码高电平范围内
              if ((IrHigh < IrHeadHigh_Max)&&(IrHigh > IrHeadHigh_Min))
              {
                IrRecStep = 2;
              }
            }
          }
          break;
  case 2:
          if ((TIM1_SR2_CC1OF==1) || (TIM1_SR2_CC2OF==1) || (TIM1_SR1_UIF==1))
          { 
            IrRecStep = 0;
          }
          else
          { 
            if ((TIM1_SR1_CC1IF == 1)&&(TIM1_SR1_CC2IF == 1))
            { 
              IrHigh = (uint)(TIM1_CCR2H); 
              IrHigh = (IrHigh << 8) + TIM1_CCR2L;
              IrCycle = (uint)(TIM1_CCR1H); 
              IrCycle = (IrCycle << 8) + TIM1_CCR1L;
              //周期是否在数据0范围内
              if ((IrCycle > IrData00_Min)&&(IrCycle < IrData00_Max))
              {
                //高电平是否在数据0范围内
                if ((IrHigh > IrData0_Min)&&(IrHigh < IrData0_Max))
                {
                  IrIndex++;
                }
                else
                {
                  IrRecStep = 0;
                }
              }
              //周期是否在数据1范围内
              else if ((IrCycle > IrData10_Min)&&(IrCycle < IrData10_Max))
              {
                //高电平是否在数据1范围内
                if ((IrHigh > IrData1_Min)&&(IrHigh < IrData1_Max))
                {
                  IrRecBuff[IrIndex >> 3] |= IrCode[IrIndex & 0x07];
                  IrIndex++;
                }
                else
                {
                  IrRecStep = 0;
                }
              }
              else
              {
                IrRecStep = 0;
              }
              if(IrIndex >= 32)
              {
                IrRecStep = 0;
                IrRecFlag = 1;
              }
            }
          }
          break;
  }
}
      
//时钟初始化
void CLK_Init(void)
{
  CLK_ECKR=0x03;//外部时钟寄存器 外部时钟准备就绪,外部时钟开
  CLK_SWCR=0x02;//切换控制寄存器 使能切换机制
  CLK_SWR=0xB4;//主时钟切换寄存器 选择HSE为主时钟源*/ 
  while (!(CLK_SWCR & 0x08));  
  CLK_CSSR=0x01;//时钟安全系统寄存器    


//初始化
void Devices_Init(void)
{
  Delay_ms(200);
  CLK_Init(); 
  Ir_Init();
  Ir_PWM_Init(); 

//主程序
void main( void )
{
  Devices_Init();
  while(1)
  {
    Ir_Receive();
    if(IrRecFlag == 1)
    {
      IrRecAddr1 = IrRecBuff[0];
      IrRecAddr2 = IrRecBuff[1];
      IrRecData1 = IrRecBuff[2];
      IrRecData2 = IrRecBuff[3];
      IrRecFlag = 0;
    }
  }

关键字:STM8  测量脉宽  红外例程 引用地址:STM8 测量脉宽——红外例程

上一篇:单片机播放WAV格式音频的理解
下一篇:STM8 块操作

推荐阅读最新更新时间:2024-03-16 16:09

STM8 ADC转换模式-------单次模式
STM8单片机ADC支持5种转换模式:单次模式,连续模式,带缓存的连续模式,单次扫描模式,连续扫描模式。 单次模式 在单次转换模式中,ADC仅在由ADC_CSR寄存器的CH 选定的通道上完成一次转换。该模式是在当CONT位为0时通过置位ADC_CR1寄存器的ADON位来启动的。 一旦转换完成,转换后的数据存储在ADC_DR寄存器中,EOC(转换结束)标志被置EOCIE 被置位将产生一个中断。 其中ADC结果的读取可以采用查询模式也可以采用中断模式。 查询模式代码如下: #include adc.h #include main.h u16 DATAH = 0; //ADC转换值高8位
[单片机]
STM8 SPI简介 主要特征
SPI简介 串行外设接口(SPI)允许芯片与其他设备以半/全双工、同步、串行方式通信。此接口可以被配置成主模式,并为从设备提供通信时钟(SCK)。接口还能以多主配置方式工作。 STM8的SPI可用于多种用途,包括带或不带第三根双向数据线的双线单工同步传输,还可使用CRC校验来进行可靠通信。 SPI主要特征 3线全双工同步传输 带或不带第三根双向数据线的双线单工同步传输 8或16位传输帧格式选择 主或从操作 8个主模式频率(最大为fMASTER/2) 从模式频率(最大为fPCLK/2) 快速通信:最大SPI速度达到10MHz 主模式和从模式下均可以由软件或硬件进行NSS管理 可编程的时钟极性和相位 可编程的数
[单片机]
STM8 UART2
#include stm8s.h #include stm8s_conf.h #include UART2.h #include stdarg.h void UART2_Config(u32 Rate) { CLK_PeripheralClockConfig(CLK_PERIPHERAL_UART1, ENABLE); GPIO_Init(UART2_PORT, TX2_PIN, GPIO_MODE_OUT_PP_LOW_FAST); GPIO_Init(UART2_PORT, RX2_PIN, GPIO_MODE_IN_PU_NO_IT); UART2_Init(Rate, U
[单片机]
STM8学习笔记三----按键实验
今天做按键的实验。青风的源码中按键的引脚定义似乎有错,和开发板原理图中的不一致。 正确的引脚定义应该是: #define KEY3_PIN GPIO_PIN_3 #define KEY2_PIN GPIO_PIN_4 #define KEY1_PIN GPIO_PIN_0 #define KEY3_PORT GPIOE #define KEY2_PORT GPIOE #define KEY1_PORT GPIOI 我编写的main主函数代码: #include stm8s.h #include stm8s_clk.h #include led.h #include ke
[单片机]
STM8入门以及程序编译、烧录、IAR使用方法(扫盲篇)
1、硬件环境:STM8S003F3P6、ST-LINK stlink V2 2、软件环境:Embedded Workbench 6.5(IarIdePm)、ST Visual Programmer(STVP) STM8以其超高的性价比,在低端单片机领域占领了很大的市场,市面上很多单片机产品都能够看到STM8的身影,下面对STM8和89C51来做简单的对比: 1、对“89C51”而言: 对“89C51”而言,其能满足大部分需求,但最初代的“89C51”不具有“ADC”、“PWM”等外设功能;而且单就“ADC芯片”而言,列举一下4点: i)、“价格方面”:以“STC89C52”(DIP-40)为例,工作电压为“+5.0V”,其
[单片机]
<font color='red'>STM8</font>入门以及程序编译、烧录、IAR使用方法(扫盲篇)
STM8单片机的中断控制(ITC)
内部中断:一般是由硬件错误或者运算过程中出错引起的,一般是不可避免的; 外部中断:是处理器的外设发出的中断请求,如定时器中断,UART接收中断,外部中断一般都可以通过中断控制器进行屏蔽; 1.ITC功能概述: ……所有IO引脚都具有外部中断能力,每个端口都有独立的中断向量以及独立的标志;外设中断能力; ……软件中断能力(TRAP) ……具有灵活的优先级和中断等级管理,支持可嵌套和同级中断管理: ——多达4个软件可编程的嵌套等级;——最多有32个中断向量,其入口地址由硬件固定;——2个不可避免的中断:RESET,TRAP;——1个不可避免的最高优先级硬件中断TL1; 2.中断的主要功能 1. 实现高速CPU和低速外设之间速度的配合;
[单片机]
STM8 ICP和IAP
在线编程(ICP)用于更新STM8整个存储器的内容。ICP使用SWIM接口把用户的程序装载到微控制器中,同时提供迅速而有效的设计迭代并且去除了不必要的封装处理和器件插槽。SWIM接口(单线接口模块)使用SWIM引脚和编程工具相连接。 相对于ICP方式,在应用编程(IAP)可使用STM8支持的任意通讯接口(I/O、I2C、SPI、UART )来下载要编入存储器中的数据。IAP允许在应用程序运行中对FLASH程序存储器的内容重新编程。然而要想使用IAP,必须通过ICP对FLASH程序存储器预先编程。请参考STM8 Flash编程手册(PM0051)和STM8 SWIM通信协议和调试模块用户手册(UM0470)来了解关于编程步骤的
[单片机]
<font color='red'>STM8</font> ICP和IAP
STM8 RAM
我关于实现IAP的理解,如果有误,希望可以得到大家的斧正 1.IAP部分程序和应用程序分开两个项目编写。 2.应用程序部分编译前要修改ICF文件,使其代码安排到IAP程序区外,如0x9000 3.IAP项目编译前也要修改ICF文件 a.修改代码编译后所在ROM中的位置,如:0x8000-0x8FFF b.按网友dianzidog 给出的方法,实现ram运行代码 ////////////////////////摘自网友dianzidog的帖子 /////////////////////////////////// icf文件里面 initialize by copy { ro section MyCod
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved