2019-06-11 16:54:44 weixin_38679924 阅读数 917
  • 单片机有很多种-1.3.第1季第3部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第3个课程,主要讲了单片机的发展史,各种主流单片机的各自特点,STC51单片机的各系列的特点以及项目中如何选型主控单片机。

    2476 人正在学习 去看看 朱有鹏

项目描述:
由三个按键分别控制LED的开关、变亮、变暗。灯的亮度调节采用单片机产生的PWM实现。
C语言代码如下:

/*-----------------------------
FileName:PWMDimming.h
Function: 头文件
Author: Zhang Kaizhou
Date: 2019-6-11 16:49:42
------------------------------*/
#include <reg52.h>
#include <string.h>
#define uchar unsigned char
#define uint unsigned int
#define PERIOD 100 // PWM信号周期为 100ms

/*主模块端口定义*/
sbit led = P1^7;
sbit onOff = P3^4;
sbit addLight = P3^5;
sbit decLight = P3^6;

/*LCD1602显示模块端口定义*/
sbit lcdrs = P1^0;
sbit lcdrw = P1^1;
sbit lcden = P2^5;

/*主模块函数声明*/
void delay(uint xms);
void keyScan();
void dimming();
void generatePWM();

/*LCD1602显示模块函数声明*/
void LCDInit();
void display(uchar dat);
void writeCommand(uchar command);
void writeData(uchar dat);
/*-------------------------------------------------
Function: 单片机PWM调光
Description: 按键控制LED灯开关,四个亮度等级的调光;
LCD1602实时显示LED灯的亮度等级。
Author: Zhang Kaizhou
Date: 2019-6-11 15:37:10
--------------------------------------------------*/
#include "PWMDimming.h"

/*全局变量定义*/
uchar brightness = 0; // 亮度标志
uint count = 0;
bit onFlag = 0; // 0-关灯 1-开灯

void main(){
	LCDInit();
	led = 1; // 上电时灯处于关闭状态
	while(1){
		keyScan();
		display(brightness);
		dimming();
		generatePWM();
	}
}

/*键盘扫描函数*/
void keyScan(){
	if(!onOff){ // 开关灯
		delay(5);
		if(!onOff){
			while(!onOff);
			led = onFlag;
			onFlag = ~onFlag;
			if(onFlag){
				brightness = 1; // 开灯初始亮度为1
			}else{
				brightness = 0;
				led = 1;
			}
		}
	}else if(onFlag){ // 灯处于开的状态
		if(!addLight){ // 变亮
			delay(5);
			if(!addLight){
				if(brightness < 4){
					while(!addLight);
					brightness++;
				}
			}
		}
		if(!decLight){ // 变暗
			delay(5);
			if(!decLight){
				if(brightness > 1){
					while(!decLight);
					brightness--;
				}
			}
		}
	}
}

/*调光程序*/
void dimming(){
	switch(brightness){
		case 1: count = 80; break; // 80%占空比
		case 2: count = 90; break; // 90%占空比
		case 3: count = 95; break; // 95%占空比
		case 4: count = 100; break; // 100%占空比
		default: break;
	}
}

/*产生PWM信号*/
void generatePWM(){
	while(onOff && addLight && decLight && brightness){
		led = 0;
		delay(count);
		led = 1;
		delay(PERIOD - count);
	}
}

/*延时函数*/
void delay(uint xms){
	uint i, j;
	for(i = xms; i > 0; i--)
		for(j = 110; j > 0; j--);
}
/*-----------------------------
FileName:display.c
Function: LCD1602显示函数
Author: Zhang Kaizhou
Date: 2019-6-11 16:49:02
------------------------------*/
#include "PWMDimming.h"
/*显示信息数组*/
uchar code table0[] = {"PWMDmimming"};
uchar code table1[] = {"Brightness:"};
uchar code table2[] = {"01234"};
uchar num = 0;

/*初始化LCD1602的设置*/
void LCDInit(){
	uchar i;
	lcden = 0; // 拉低使能端,准备产生使能高脉冲信号
	writeCommand(0x38); // 显示模式设置(16x2, 5x7点阵,8位数据接口)
	writeCommand(0x0c); // 开显示,不显示光标
	writeCommand(0x06); // 写一个字符后地址指针自动加1
	writeCommand(0x01); // 显示清零,数据指针清零
	
	/*LCD上电界面*/
	writeCommand(0x80); // 将数据指针定位到第一行首
	for(i = 0; i < strlen(table0); i++){
		writeData(table0[i]);
		delay(5);
	}
	
	writeCommand(0x80 + 0x40); // 将数据指针定位到第二行首
	for(i = 0; i < strlen(table1); i++){
		writeData(table1[i]);
		delay(5);
	}
}

/*LCD显示函数*/
void display(uchar dat){
	writeCommand(0x80 + 0x40 + strlen(table1));
	writeData(table2[dat]);
	delay(5);
}

/*写指令函数*/
void writeCommand(uchar command){
	lcdrs = 0; // 命令选择
	lcdrw = 0;
	P0 = command;
	delay(5);
	
	lcden = 1; // 产生一个正脉冲使能信号
	delay(5);
	lcden = 0;
}

/*写数据函数*/
void writeData(uchar dat){
	lcdrs = 1; // 数据选择
	lcdrw = 0;
	P0 = dat;
	delay(5);
	
	lcden = 1;
	delay(5);
	lcden = 0;
}

扩展:
1.可根据需求增加或减少LED灯的亮度等级;
2.可通过改变个亮度等级对应的PWM的占空比来改变个亮度等级对应的灯的亮度;
3.因为此处PWM调制主要是根据占空比的不同控制LED的亮度,因此用软件延时即可。

2018-01-08 20:04:11 m0_37277616 阅读数 1908
  • 单片机有很多种-1.3.第1季第3部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第3个课程,主要讲了单片机的发展史,各种主流单片机的各自特点,STC51单片机的各系列的特点以及项目中如何选型主控单片机。

    2476 人正在学习 去看看 朱有鹏

1.什么是PWM?
PWM在百度的解释是一种对模拟信号电平进行数字编码的方法。通过高分辨率计数器的使用,方波的占空比被调制用来对一个具体模拟信号的电平进行编码。PWM信号仍然是数字的,因为在给定的任何时刻,满幅值的直流供电要么完全有(ON),要么完全无(OFF)。电压或电流源是以一种通(ON)或断(OFF)的重复脉冲序列被加到模拟负载上去的。通的时候即是直流供电被加到负载上的时候,断的时候即是供电被断开的时候。只要带宽足够,任何模拟值都可以使用PWM进行编码。
我对百度的解释比较认同,但是由于我是实用派,还是觉得有些复杂,不是很好理解。众所周知,我们国家的交流电是50HZ,代表着一秒内有50次的变化——从低电平到高电平、高电平到低电平,周而复始。而直流电却是单一的高电平。我就简单的认为PWM就是将直流电的波形频率变成类似交流电波形频率,同时还能控制脉宽(脉冲宽度)的技术。

2.怎么编写PWM程序?
上文我简单的给PWM下了一个定义——PWM就是将直流电的波形频率变成类似交流电波形频率,同时还能控制脉宽(脉冲宽度)的技术。那么我们现在就只需要分析交流电的波形是怎么样的,然后通过编程让单片机发出类似交流电的波形并控制每个波形的宽度就行了。
首先交流电的波形是没有方向的,所以这一点我们是不可能做到的,毕竟正负极摆在这里,我们能做到的是和交流电一样的频率。交流电一秒钟的频率是50HZ,也就是在一秒内变化50次,那我们同样让直流电变化50次,并控制变化的时间不就达到了和交流电一样的频率。
理清楚了思路,我们就可以开始编程了。

#include<reg52.h>

/*
实验 STC89C52 
PWM波的使用与分析
2018-1-8
*/
//宏定义
#define uchar unsigned char
#define uint unsigned int

//定义IO口
sbit led = P1^0;

//定义变量
uchar num = 50;
bit bz = 1;

//函数声明
void init();    //定时器0 初始化

void main()
{
    init();     //调用初始化函数
    while(1)
    {   
    }   
}

void init(void)
{    
    TMOD = 0x11;     //设置定时器的工作模式
    EA = 1;     //开总中断

    //开定时器0
    TH0 = (65535-500)/256;  //装初值 
    TL0 = (65535-500)%256;  
    ET0 = 1;    //开定时器0中断
    TR0 = 1;    //启动定时器0

    //开定时器1
    TH1 = (65535-45872)/256;    //装初值 
    TL1 = (65535-45872)%256;    
    ET1 = 1;    //开定时器1中断
    TR1 = 1;    //启动定时器1
}

void T0_time(void)  interrupt 1
{
    static uchar t0_cnt=0;
    TH0=(65535-500)/256;   //0.5ms
    TL0=(65536-500)%256;
    t0_cnt++;
    if(t0_cnt < num)    //当小于临界值时 灯灭
    {
        led = 1;

    }
    if(t0_cnt > num)    //当高于临界值时 灯亮
    {
        led = 0;
    }
    if(t0_cnt > 40)     //当亮了一个周期以后 复位
    {
        t0_cnt = 0;
    }

}

void T1_time(void)  interrupt 3
{
    static uchar t1_cnt=0;
    TH1=(65535-45872)/256;     //50ms
    TL1=(65536-45872)%256;
    t1_cnt++;
    if(t1_cnt == 5)
    {
        t1_cnt = 0;

        if(bz == 1)
        {
            num--;
        }
        if(bz == 0)
        {
            num++;
        }
        if(num == 0)
        {
            bz = 0;
        }
        if(num == 41)
        {
            bz = 1;
        }
    }

}

本段程序,我使用了两个定时器,定时器0定时0.5毫秒用来控制直流电在一秒内变化的周期,定时器1定时50毫秒用来控制直流电在每一个周期内高电平占用周期的时间,也即是控制脉宽。
通过计算,1秒内产生50次变化,即20毫秒产生一个变化,定时器0每0.5毫秒产生一次中断,产生中断达到40次时刚好一个周期结束。而脉宽我用定时器1来调节,通过改变临界值num的值,让高电平在一个周期内的时间做出不同的变化。

3.PWM的使用和分析
由于条件有限,不能用示波器来测量单片机发出的直流电的频率是多少,但是我相信即使有错误,误差也不会很大,产生误差的原因大致与晶振的频率有关。
虽然没有测得频率是多少,但我还是用万用表测量了它的电压,测得电压用0V慢慢的升到了4.5V。外在表现为LED灯呈现了呼吸灯的效果,从暗到亮,从亮到暗。
通过本次实验可以知道,PWM可以改变电压的大小,从而可以用这电压控制一个元件的目的。
程序下载地址 http://download.csdn.net/download/m0_37277616/10195051
新人发博客 ——有什么解释的不对的地方请多多指教。

2018-01-25 16:48:44 qq_35158400 阅读数 3602
  • 单片机有很多种-1.3.第1季第3部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第3个课程,主要讲了单片机的发展史,各种主流单片机的各自特点,STC51单片机的各系列的特点以及项目中如何选型主控单片机。

    2476 人正在学习 去看看 朱有鹏

       本文介绍如何通过IO口输入的电平来控制STC15F2K60S2系列单片机输出pwm,试验基于STC15L2K60S2型号单片机。

       STC15F2K60S2系列单片机有3路pwm输出引脚,STC15F2K60S2系列单片机的CCP/PWM/PCA可以在3组不同管脚之间进行切换:

[CCP0/P1.1, CCP1/P1.0, CCP2/CCP2_2/P3.7];
[CCP0_2/P3.5, CCP1_2/P3.6, CCP2/CCP2_2/P3.7];
[CCP0_3/P2.5, CCP1_3/P2.6, CCP2_3/P2.7]。




如果不配置这个寄存器,PCA_PMW2默认输出端口是p3.7,串口1默认P3.0/RxD,P3.1/TxD。

//p1.0读输入电平,p3.7输出pwm值
//本程序输出的pwm频率为50Hz
#include<reg51.h>
sfr CCON = 0xd8;   //PCA控制寄存器CCON
sfr CMOD = 0xd9;   //PCA工作模式寄存器
sfr CCAPM2 = 0xdc; //PCA比较/捕获寄存器CCAPM0、CCAPM1和CCAPM2
sfr CL = 0xe9;     //PCA的16位计数器 — 低8位CL和高8位CH
sfr CH = 0xf9;
sfr CCAP2L = 0xec;
sfr CCAP2H = 0xfc;
/*PCA捕捉/比较寄存器 — CCAPnL(低位字节)和CCAPnH(高位字节)
当PCA模块用于捕获或比较时,它们用于保存各个模块的16位捕捉计数值;当PCA模块用于PWM模式时,它们用来控制输出的占空比。
其中,n = 0、1、2,分别对应模块0、模式1和模块2。复位值均为00H。它们对应的地址分别为:
CCAP0L — EAH、CCAP0H — FAH:模块0的捕捉/比较寄存器。
CCAP1L — EBH、CCAP1H — FBH:模块1的捕捉/比较寄存器。
CCAP2L — ECH、CCAP2H — FCH:模块2的捕捉/比较寄存器。*/

sfr P1M1 = 0x91;  //配置IO输出输入模式
sfr P1M0 = 0x92;

sfr PCA_PMW2 = 0xf4; //PCA模块2的PWM寄存器 地址 为0xf4。
sfr AUXR = 0x8e; //辅助寄存器

sbit HL=P1^0;

void timer0_isr(void) interrupt 1 {
	TH0= (65536 - 936) / 256;  //重装初值
	TL0= (65536 - 936) % 256;  //重装初值
}

/*********************Timer0初始化函数***********************/

void timer0_init(void)
{
	AUXR |= 0x80;                     //定时器时钟1T模式,|=0x80 就是将最高位置1。AUXR &= 0xBF;定时器时钟12T模式 ,&=0xBF就是只操作AUXR的第7位,其他位不动。
	TMOD= 0x01;                       //T0工作方式1,16位自动重载
	TH0= (65536 - 936) / 256;         //对机器脉冲计数936个计满溢出引发中断
	TL0= (65536 - 936) % 256;
	EA= 1;                             //开总中断
	ET0= 1;                            //开T0中断
	TR0= 1;                            //启动定时器T0
}

void pwm0_init(void)
{
	P1M0 = 0x00;  //P1口用传统51准双向口模式
	P1M1 = 0x00;
	CCAP2L = 0xF4;//低电平的占空比:CCAP2L/256,高电平的站控比:1-CCAP2L/256。
	//CCAP2H = 0xF4;   //由于工作模式是8位PMW,所以CCAP2H是不参与计数匹配
	CMOD = 0x84;  // 空闲模式下PCA计数器停止工作;定时器0溢出做PCA模块的时钟源
	CCON= 0x00;
	CL= 0x00;           //当计数数值与CCAP2L匹配,电平翻转
	CH= 0x00;
	PCA_PMW2= 0x00;     //8位PMW,占空比的第九位EPC0L为0
	CCAPM2= 0x42;       //允许比较,P3.7输出,CCAPM2:PCA模块2的比较/捕获寄存器,不允许中断
	                    //要使能PWM模式,模块CCAPMn寄存器的PWMn和ECOMn位必须置位。
	CCON= 0x40;         //允许PAC计数
}

void main(void)
{
	timer0_init();
	pwm0_init();
	while(1) {
		if(HL== 1) {    //如果P1.0输入高电平
			CCAP2L = 0xEC;//低电平的占空比:CCAP2L/256,高电平的占控比:1 - CCAP2L/256。
		}
		if(HL== 0){     //如果P1.0输入低电平
			CCAP2L = 0xF4;//低电平的占空比:CCAP2L/256,高电平的占控比:1 - CCAP2L/256。
	  }
	}
}

定时器的配置可以参考以下链接,http://blog.csdn.net/sjong/article/details/73380499,定时器需要重载初值,定时器要工作在1T模式下。


当P1.0口输入为高电平时,P3.7输出的波形图如下。



当P1.0输入为低电平时,P3.7输出的波形图如下。



注意,STC15L2K60S2型号的单片机输入电源VCC为3.3V,IO口输入低于0.8V为低电平,高于2.2V为高电平。

2020-01-01 21:11:10 zhongvv 阅读数 100
  • 单片机有很多种-1.3.第1季第3部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第3个课程,主要讲了单片机的发展史,各种主流单片机的各自特点,STC51单片机的各系列的特点以及项目中如何选型主控单片机。

    2476 人正在学习 去看看 朱有鹏

         应广单片机Otp单核系列主要有以下几个系列,15x系列为纯iO,13x系列为带12bit的adc,17x系列为带8bit的adc,现在我用pms132B写个adc/pwm例程,方便大家快速上手.不多说,上代码.

#include    "extern.h"


/**********adc*****************/
Word usAdcSum;
Word usAdcSumBak;

BIT        THR             :PB.0;
BIT        PWM             :PA.3;
/*定时器初始化*/
void PwmTmr2Init ( void )
{
    tm2ct = 0x0;/*计数值*/
    //pwm duty
    tm2b = 0;//START_PWM_CNT;
    //8 位 pwm, 预分频 = 64, 分频 = 2, frq=970hz
    tm2s = 0b0_11_00000;
    //0010=HIRC输出 ,01= PB2,10=PA3,11=PB4, PWM模式,禁用极性反转
    tm2c = 0b0010_10_1_0;
}

void GetAdc(void)    //ADC采样处理
{
     BYTE  ucCnt;
     
     $ ADCC Enable, THR    ;
     
     //8次采样做平均/
     ucCnt=8;
     //初始化
     usAdcSum=0;
     while ( ucCnt-- )
     {
         AD_Start=1;
        .wait1    AD_Done;
        //adc 采样值,12bit实际使用8bit
        usAdcSum +=ADCRH;
     }    
     //取平均值输出
     usAdcSum=usAdcSum>>3;  //temp除以8
}


void    FPPA0 (void)
{
    .ADJUST_IC    SYSCLK=IHRC/2        //    SYSCLK=IHRC/2

    //    Insert Initial Code
    $ THR  in;
    $ PWM  out,low;


    /*bit config start
    b7:5@001=2V参考;000=VDD;
    b4@0f通道选择器
    b3:2@f通道band-gap参考电压选择
    b1:0@00=rsv
    bit config end*/
    adcrgc=0b000_0_00_00;

    
    PwmTmr2Init();
    while (1)
    {
        /**/
        GetAdc();
        /*当pwm占空比为0,会有关不断的现象,要做特殊处理*/
        if(usAdcSumBak!=usAdcSum)
        {
            usAdcSumBak=usAdcSum;

           /*更新占空比*/
            tm2b=usAdcSum$0;

           /*pwm输出为0*/
            if(!usAdcSum$0)
            {

               /*关闭pwm输出*/
                tm2c = 0b0010_00_1_0;
                PWM=0;
            } 
            else
            {

               /*打开pwm输出*/
                tm2c = 0b0010_10_1_0;
            }
        }

    }
}


void    Interrupt (void)
{
    pushaf;

    if (Intrq.T16)
    {    //    T16 Trig
        //    User can add code
        Intrq.T16    =    0;
        //...
    }

    popaf;
}

/*有啥问题可以留言,也可以联系本人QQ85547259*/

2018-01-21 20:09:34 qq_35158400 阅读数 4380
  • 单片机有很多种-1.3.第1季第3部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第3个课程,主要讲了单片机的发展史,各种主流单片机的各自特点,STC51单片机的各系列的特点以及项目中如何选型主控单片机。

    2476 人正在学习 去看看 朱有鹏

本文主要介绍怎么通过遥控接收机的信号控制单片机的IO口。试验器材:

天地飞WFT09II 9通道2.4G遥控器+接收机

STC15F104W单片机


这里接收机输出的是频率为50hz,周期为20mspwm波形,通过单片机外部中断口接收pwm信号,启用定时器/计数器对pwm高电平的持续时间进行计数。

Arduino中的pulseIn函数可以直截了当地读取pwm的值,可以参考其底层的实现方法,这里有一个链接介绍pulseIn函数读取pwm的思想。

http://blog.csdn.net/soso90soso/article/details/78599621?locationNum=5&fps=1

文中关键部分:

unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout) {
  pinMode(pin, INPUT);
  uint32_t start = micros();
  while(digitalRead(pin) == state && (micros() - start) < timeout);
  while(digitalRead(pin) != state && (micros() - start) < timeout);
  start = micros();
  while(digitalRead(pin) == state && (micros() - start) < timeout);
  return micros() - start;
}

微妙级,死循环读取引脚电平。因为不确定IO口接收到输入的pwm的瞬间是高电平还是低电平,所以While循环里先判断高电平,再判断低电平,再判断一次高电平,从而获得准确的占空比。

至于怎么在单片机上读取pwm呢?在网上查找一些资料后,我了解到可以通过外部中断+定时器来实现。最初我参考这个源码:

//转发请注明:http://bbs.5imx.com
//芯片型号为STC15F100W-STC15F104W,烧写程序时请选择IRC频率12M.
//STC15F100W芯片的P3.2脚为模型接收机PWM信号输入脚.
//本程序可根据个人需求更改判断变量a的值来达到相应的要求.
//变量a的值单位为微秒:1000us=1ms,1500=1.5ms,2000=2.0ms.
#include<reg51.h>
sfr AUXR = 0x8E;
unsigned int a=0;
sbit led1=P3^3;
sbit led2=P3^4;
sbit led3=P3^5;
bit HL;
                       
void Timer0Init(void)		
{
	AUXR &= 0x7F;		
	TMOD &= 0xF0;	
	TL0 = 0x00;		
	TH0 = 0x00;		
	TF0 = 0;	
	TR0 = 0;		
}

void main()
{   
    EA   = 1;
	INT0 = 1;
	EX0  = 1; 
	IT0  = 0;                    
    Timer0Init();
while(1){  
		 if(a>980&&a<1020)led2=0;  else led2=1;
		 if(a>1480&&a<1520)led3=0; else led3=1;
        }
}

void INT_0 (void) interrupt 0  using 2
{
   HL = INT0;
   if(HL==1)TR0 = 1;
   if(HL==0){
   TR0 = 0;
   a   = TH0;
   a   = a*256+TL0;
   TL0 = 0x00;
   TH0 = 0x00; 
              }
}
这个代码里面有一个问题就是,当单片机满足中断条件,就会不断跳到外部中断处理函数中,感觉这样太占用cpu资源,可以编写一个函数,在监听pwm值时开启外部中断,在获取到pwm值时关闭中断。具体方法如下:

#include<reg51.h>
sfr AUXR = 0x8E;
unsigned int a0=0;
unsigned int a1=0;
//sbit led1=P3^3;
sbit led2=P3^4;
sbit led1=P3^5;
bit HL;
                   
void pulseIn0();
void pulseIn1();


void Timer0Init(void)
{
  AUXR &= 0x7F;
  TMOD &= 0xF0;
  TL0 = 0x00;
  TH0 = 0x00;
  TF0 = 0;
  TR0 = 0;
}


void main()
{   
  EA   = 1;
  //INT0 = 1;
  EX0  = 0; 
  IT0  = 0;  
  EX1  = 0; 
  IT1  = 0;
  Timer0Init();
  while(1){  
    pulseIn1();
    if(a0>980&&a0<1020)led2=0;  else led2=1;
    pulseIn0();
    if(a1>1480&&a1<1520)led1=0; else led1=1;
  }
}


void INT_0 (void) interrupt 0  using 2
{
   HL = INT0;
   if(HL==1)TR0 = 1;
   if(HL==0){
     TR0 = 0;
     a0   = TH0;
     a0   = a0*256+TL0;
     TL0 = 0x00;
     TH0 = 0x00; 
     EX0  = 0; 
   }
}
void INT_1 (void) interrupt 2  using 2
{
   HL = INT1;
   if(HL==1)TR0 = 1;
   if(HL==0){
     TR0 = 0;
     a1   = TH0;
     a1  = a1*256+TL0;
     TL0 = 0x00;
     TH0 = 0x00; 
     EX1  = 0; 
   }
}
void pulseIn0(){
  while(INT0==1);
  EX0  = 1; 
}
void pulseIn1(){
  while(INT1==1);
  EX1  = 1; 
}
STC15F104W单片机外部中断0(INT0)和外部中断1(INT1)触发有两种发方式,上升沿或下降沿均可发方式和仅下降沿发方式。
TCON寄存器中的IT0/TCON.0和IT1/TCON.2决定了外部中断0和1是上升沿和下降沿均可发还是仅下降沿发。如果ITx = 0(x = 0,1),那么系统在INTx(x = 0,1)脚探测到上升沿或下降沿后均可产生外部中断。如果ITx = 1(x = 0,1),那么系统在INTx( x= 0,1)脚探测下降沿后才可产生外部中断。

程序中

IT0  = 0;  
IT1  = 0;

所以上升沿或下降沿后均可产生外部中断,我设想是通过上升沿触发中断,

void pulseIn0(){
  while(INT0==1);
  EX0  = 1; 
}
该段代码的意思是,如果接收到的pwm信号正处于高电平,先进入死循环,等pwm信号处于低电平再开启中断,那么下一个上升沿即可触发中断,触发中断后立即启用定时器0正好可以对高电平进行计数,到下一个下降沿时关闭中断。


试验效果如下:

INT1口接收到的pwm信号满足a1>1480&&a1<1520,led1熄灭。

而且用Arduino读取到的pwm值也在这个区间内,由此可见,用这种方法读取pwm的值精度是很高的,以后可以用STC15F104W单片机代替Arduino,通过pwm控制单片机的IO口。




PWM51单片机呼吸灯

博文 来自: Zach_z
没有更多推荐了,返回首页