精华内容
下载资源
问答
  • STC15F104W

    2014-08-22 15:30:35
    STC15F104W-35I-SOP_PDF_C26928.rar
  • STC15F104W单片机串口发送接收例程,可参考,有源代码! STC15F104W单片机串口发送接收例程,可参考,有源代码! STC15F104W单片机串口发送接收例程,可参考,有源代码!
  • STC15F104W学习遥控器

    2016-06-14 21:57:54
    STC15F104W学习遥控器
  • STC15F104W的串口发送函数,测试正常好用。作为无线发送部分配合无线的串口模块挺好用的。实际测试48小时,每100ms发送2个字节,没遇到故障。
  • 旋转LED指尖陀螺_STC15f104w
  • 我在学STC15F104W这个芯片,他有五个外部中断,那么中断优先级是怎么规定的我没查到,有哪位大神知道吗
  • STC15F104W驱动WS2812

    2021-04-08 14:21:05
    STC15F104W驱动WS2812 提示:学习目标:了解WS2812的驱动原理,写出驱动代码。 内容: 提示:这里可以添加要学的内容 例如: 1、 连接WS2812时序; 2、 基于STC15F104W写出驱动程序。 3、 软件调试计算程序的机器...

    STC15F104W驱动WS2812

    提示:学习目标:了解WS2812的驱动原理,写出驱动代码。


    内容:

    提示:这里可以添加要学的内容
    例如:
    1、 连接WS2812时序;
    2、 基于STC15F104W写出驱动程序。
    3、 软件调试计算程序的机器周期。
    4、 测试程序,并根据示波器得到的实际机器周期时间重新调整驱动程序


    正文:

    1,WS2812时序

    WS2812是一个集控制电路与发光电路于一体的智能外控LED光源,每个ws2812均含有4个引脚,引脚功能如下图:
    在这里插入图片描述
    WS2812可采用级联的方式,将上一个WS2812的DOUT引脚连接到下一个WS2812的DIN引脚,即可实现一个引脚控制多个WS2812。一般自己设计电路时还要在电源输入处添加一个0.1uF的小电容进行滤波。注意,虽然理论上可以连接足够多的ws2812,但是使用时要注意驱动电压和驱动电流是否足够驱动这些彩灯。
    在这里插入图片描述
    由于只有一个引脚控制ws2812,所以我们只能通过控制引脚输出高、低电平的时间,来让WS2812知道我们想让他显示哪一个灯,显示什么颜色。
    想要让1个ws2812显示我们想要的颜色,我们需要给它发送颜色数据。每一个ws2812的颜色数据都是24位:8位绿色+8位红色+8位蓝色。
    在这里插入图片描述
    如果我们想控制1个ws2812,我们发送24位颜色数据;如果我们想控制2个ws2812,我们需要连续发送48位颜色数据;如果我们想控制n个ws2812,我们需要连续发送n*24位颜色数据。
    在这里插入图片描述

    那么ws2812如何知道我们发送的每一个位的数据是“1”还是“0”呢?
    WS2812手册中对于数据有明确的时间定义:
    在这里插入图片描述
    在这里插入图片描述
    可以看出,当我们想要发送一个位的数据时,如果这个位是“1”,我们就控制单片机的引脚输出高电平0.85us,然后控制引脚输出低电平0.40us;如果这个位是“0”,则控制引脚输出高电平0.40us,然后控制引脚输出低电平0.85us。

    而如果我们想控制1个灯显示颜色,我们需要发送24个位的颜色数据给ws2812。如果我们想控制n个灯显示颜色,我们从第1个灯的颜色数据开始发送,直至发送完n*24个数据。最后我们需要控制单片机引脚输出低电平超过50us,让彩灯显示颜色。

    2,写出驱动程序

    注意,STC15F104W只有8个引脚,我们一般采用内部晶振电路。下面的代码都是基于12MHz的晶振频率写的。WS2812对于单片机的引脚时序要求比较高。我们一般调用intrins.h这个头文件的机器周期函数,nop()函数执行一次占用一个机器周期(此处时钟周期和机器周期相等),所以每条机器周期时间为1/12MHz=83.3us。(代码中很多处使用宏定义,宏定义在预编译阶段程序就完成代码替代工作,不会影响程序的执行时间,且修改方便)
    下面是h文件代码:

    #ifndef __WS2812_H
    #define __WS2812_H
    
    //头文件区
    #include <STC15F2K60S2.H>
    #include <intrins.h>
    
    //用户修改参数区
    //#define WS2812_FREQUENCY
    #define RGB_PIN           P33                       //控制彩灯引脚(需要配置为强推挽输出)
    #define WS2812_MAX        25                        //彩灯最大个数
    #define WS2812_NUMBERS    8                         //彩灯个数
    
    
    #define RED               0xff0000                  //红色
    #define GREEN             0x00ff00                  //绿色
    #define BLUE              0x0000ff                  //蓝色
    #define BLACK             0x000000                  //熄灭
    #define WHITE             0xffffff                  //白色
    
    #define RGB_PIN_H()  RGB_PIN = 1
    #define RGB_PIN_L()  RGB_PIN = 0
    #define delay1NOP()  _nop_();
    #define delay1NOP()  _nop_();
    #define delay2NOP()  delay1NOP(); _nop_();
    #define delay3NOP()  delay2NOP();_nop_();
    #define delay5NOP()  delay3NOP();delay2NOP();
    #define delay7NOP()  delay5NOP();delay2NOP();
    
    void Ws2812b_WriteByte(unsigned char byte);//发送一个字节数据(@12.000MHz,理论每个机器周期83ns,测试约为76ns)                                                      
    void setLedCount(unsigned char count);//设置彩灯数目,范围0-25.                                                           
    unsigned char getLedCount();//彩灯数目查询函数                                                                     
    void rgb_SetColor(unsigned char LedId, unsigned long color);//设置彩灯颜色                                     
    void rgb_SetRGB(unsigned char LedId, unsigned long red, unsigned long green, unsigned long blue);//设置彩灯颜色
    void rgb_SendArray();//发送彩灯数据                                                                            
    #endif                                                                      
    

    接着我们对c代码进行详解。
    首先调用h文件,然后定义一个数组,用来存放彩灯的颜色数据。这里数据存放在data空间(空间有限,只能存放25个灯左右的数据),后面有需要再优化到xdata空间。ledsCount 记录实际我们想要控制的彩灯的数目,nbLedsBytes 用来记录彩灯的数据个数(一个灯需要3个字节)。

    #include "ws2812.h"
    
    unsigned char LedsArray[WS2812_MAX * 3];      //定义颜色数据存储数组
    unsigned int ledsCount = WS2812_NUMBERS;      //定义实际彩灯默认个数
    unsigned int nbLedsBytes = WS2812_NUMBERS*3;  //定义实际彩灯颜色数据个数
    

    接着我们开始编写彩灯的设置数目函数,查询数目函数,以及两个设置指定彩灯颜色的函数。

    //设置彩灯数目,范围0-25.
    void setLedCount(unsigned char count)
    {
        ledsCount = WS2812_MAX > count ? count : WS2812_MAX;
        nbLedsBytes = ledsCount*3;
    }
    
    //彩灯数目查询函数
    unsigned char getLedCount()
    {
        return ledsCount;
    }
    
    //设置彩灯颜色(在这里我将绿和红色进行颠倒,这样比较符合我们日常生活的红绿蓝的顺序)
    void rgb_SetColor(unsigned char LedId, unsigned long color)
    {
        if( LedId > ledsCount )
        {
            return;    //to avoid overflow
        }
        LedsArray[LedId * 3]     = (color>>8)&0xff;
        LedsArray[LedId * 3 + 1] = (color>>16)&0xff;
        LedsArray[LedId * 3 + 2] = (color>>0)&0xff;
    }
    
    //设置彩灯颜色
    void rgb_SetRGB(unsigned char LedId, unsigned long red, unsigned long green, unsigned long blue)
    {
        unsigned long Color=red<<16|green<<8|blue;
        rgb_SetColor(LedId,Color);
    }
    

    然后我们对彩灯数据通过引脚发送出去。注意,发送彩灯数据的过程中,请将中断关闭,否则有可能会导致数据发送到一半被中断打断,导致显示异常。Ws2812b_WriteByte()函数是这个驱动代码的核心。

    //发送彩灯数据
    void rgb_SendArray()
    {
        unsigned int i;
        bit a=EA;
        //发送数据
        EA=0;
        for(i=0; i<nbLedsBytes; i++)
            Ws2812b_WriteByte(LedsArray[i]);
        EA=a;
    }
    

    下面的Ws2812b_WriteByte函数是我基于stc15f104w调试的。我写过不同单片机的驱动。不同单片机的每条指令花费的时间都不一样。如果您想要采用其他系列的单片机,我们只需要修改Ws2812b_WriteByte()函数里面的内容即可。其他的函数可以不做修改。方便代码的移植。
    主要修改的地方是高电平总的拉高时间。这里之所以不对“1”和“0”的内容进行函数封装,是为了我自己调试的方便。如果您觉得代码不够简短好看,您可以将判断条件里面的内容用宏定义进行一下封装。

    /*
    //使用12.000MHz频率,理论每个机器周期83ns,实际测试约为76ns。
    //下面都是基于76ns纳秒一个机器周期计算的。
    //测试时发现可以支持12-20Mhz频率。
    //如果想要使用11.0592Mhz频率,在h文件取消“#define WS2812_FREQUENCY”的注释
    //在实际测试中发现,ws2812对高电平时间较为敏感,对低电平时间不敏感
    //也就是说,低电平时间可以稍微长一些也不会影响程序,但是高电平时间需要控制的比较准确才行。
    */
    void Ws2812b_WriteByte(unsigned char byte)
    {
    #ifndef WS2812_FREQUENCY
        if(byte & 0x80)
        {
            RGB_PIN_H();//4个机器周期(STC15F104W的拉高拉低都需要4个机器周期,其他系列暂时不知道,但是很大可能不是4个机器周期)
            delay7NOP();//7个机器周期
            RGB_PIN_L();//4+8(跳出这个if判断需要5个机器周期,再进入下一个if判断需要3个机器周期)
        }
        else
        {
            RGB_PIN_H();
            delay2NOP();//4+2
            RGB_PIN_L();
            delay3NOP();//4+3+5(跳出这个else需要3个机器周期,进入下一个else则需要2个机器周期)
        }
        if(byte & 0x40)
        {
            RGB_PIN_H();//
            delay7NOP();//4+7
            RGB_PIN_L();//4+8
        }
        else
        {
            RGB_PIN_H();
            delay2NOP();//4+2
            RGB_PIN_L();
            delay3NOP();//4+3+5
        }
        if(byte & 0x20)
        {
            RGB_PIN_H();//
            delay7NOP();//4+7
            RGB_PIN_L();//4+8
        }
        else
        {
            RGB_PIN_H();
            delay2NOP();//4+2
            RGB_PIN_L();
            delay3NOP();//4+3+5
        }
        if(byte & 0x10)
        {
            RGB_PIN_H();//
            delay7NOP();//4+7
            RGB_PIN_L();//4+8
        }
        else
        {
            RGB_PIN_H();
            delay2NOP();//4+2
            RGB_PIN_L();
            delay3NOP();//4+3+5
        }
        if(byte & 0x8)
        {
            RGB_PIN_H();//
            delay7NOP();//4+7
            RGB_PIN_L();//4+8
        }
        else
        {
            RGB_PIN_H();
            delay2NOP();//4+2
            RGB_PIN_L();
            delay3NOP();//4+3+5
        }
        if(byte & 0x4)
        {
            RGB_PIN_H();//
            delay7NOP();//4+7
            RGB_PIN_L();//4+8
        }
        else
        {
            RGB_PIN_H();
            delay2NOP();//4+2
            RGB_PIN_L();
            delay3NOP();//4+3+5
        }
        if(byte & 0x2)
        {
            RGB_PIN_H();//
            delay7NOP();//4+7
            RGB_PIN_L();//4+8
        }
        else
        {
            RGB_PIN_H();
            delay2NOP();//4+2
            RGB_PIN_L();
            delay3NOP();//4+3+5
        }
        if(byte & 0x1)
        {
            RGB_PIN_H();//
            delay7NOP();//4+7
            RGB_PIN_L();//4+8
        }
        else
        {
            RGB_PIN_H();
            delay2NOP();//4+2
            RGB_PIN_L();
            delay3NOP();//4+3+5
        }
    #else
        if(byte & 0x80)
        {
            RGB_PIN_H();//
            delay5NOP();//4+5
            RGB_PIN_L();//4+8
        }
        else
        {
            RGB_PIN_H();
            delay1NOP();//4+1
            RGB_PIN_L();
            delay2NOP();//4+2+5
        }
        if(byte & 0x40)
        {
            RGB_PIN_H();//
            delay5NOP();//4+5
            RGB_PIN_L();//4+8
        }
        else
        {
            RGB_PIN_H();
            delay1NOP();//4+1
            RGB_PIN_L();
            delay2NOP();//4+2+5
        }
        if(byte & 0x20)
        {
            RGB_PIN_H();//
            delay5NOP();//4+5
            RGB_PIN_L();//4+8
        }
        else
        {
            RGB_PIN_H();
            delay1NOP();//4+1
            RGB_PIN_L();
            delay2NOP();//4+2+5
        }
        if(byte & 0x10)
        {
            RGB_PIN_H();//
            delay5NOP();//4+5
            RGB_PIN_L();//4+8
        }
        else
        {
            RGB_PIN_H();
            delay1NOP();//4+1
            RGB_PIN_L();
            delay2NOP();//4+2+5
        }
        if(byte & 0x8)
        {
            RGB_PIN_H();//
            delay5NOP();//4+5
            RGB_PIN_L();//4+8
        }
        else
        {
            RGB_PIN_H();
            delay1NOP();//4+1
            RGB_PIN_L();
            delay2NOP();//4+2+5
        }
        if(byte & 0x4)
        {
            RGB_PIN_H();//
            delay5NOP();//4+5
            RGB_PIN_L();//4+8
        }
        else
        {
            RGB_PIN_H();
            delay1NOP();//4+1
            RGB_PIN_L();
            delay2NOP();//4+2+5
        }
        if(byte & 0x2)
        {
            RGB_PIN_H();//
            delay5NOP();//4+5
            RGB_PIN_L();//4+8
        }
        else
        {
            RGB_PIN_H();
            delay1NOP();//4+1
            RGB_PIN_L();
            delay2NOP();//4+2+5
        }
        if(byte & 0x1)
        {
            RGB_PIN_H();//
            delay5NOP();//4+5
            RGB_PIN_L();//4+8
        }
        else
        {
            RGB_PIN_H();
            delay1NOP();//4+1
            RGB_PIN_L();
            delay2NOP();//4+2+5
        }
    #endif
    }
    

    main文件里面,我是用stc生成了一个300ms的延时函数。让程序每隔300ms更换一下颜色并输出。红绿蓝三色交替闪烁。

    #include <STC15F2K60S2.H>
    #include "ws2812.h"
    void Delay300ms();//@12.000MHz
    void main()
    {
        int i=0;
        setLedCount(12);//可以设置0-25之间的任何数目,根据实际情况而定
        rgb_SetRGB(0,0,0,0);//设置第一个灯关闭(这里作为使用示例,下面的rgb_SetColor覆盖了这个函数的作用)
        while(1)
        {
            for(i=0; i<getLedCount(); i++)//设置所有的灯为红色
            {
                rgb_SetColor(i,RED);
            }
            rgb_SendArray();//发送给ws2812,显示颜色
            Delay300ms();
            for(i=0; i<getLedCount(); i++)//设置所有的灯为绿色
            {
                rgb_SetColor(i,GREEN);
            }
            rgb_SendArray();//发送给ws2812,显示颜色
            Delay300ms();
            for(i=0; i<getLedCount(); i++)//设置所有的灯为蓝色
            {
                rgb_SetColor(i,BLUE);
            }
            rgb_SendArray();//发送给ws2812,显示颜色
            Delay300ms();
        }
    }
    void Delay300ms()//@12.000MHz
    {
        unsigned char i, j, k;
        _nop_();
        _nop_();
        i = 14;
        j = 174;
        k = 224;
        do
        {
            do
            {
                while (--k);
            } while (--j);
        } while (--i);
    }
    

    3,软件调试

    确保您的芯片型号选择正确。
    在这里插入图片描述
    填写软件调试的晶振频率,我这里使用16MHz(只是用来软件计算机器周期,和实际晶振无关)。1/16MHz=62.5ns。如果采用12MHz,我计算机器周期不太方便。
    在这里插入图片描述
    点击调试。没有配置时默认是软件调试模式。在这里插入图片描述
    点击引脚信号的逻辑分析。
    在这里插入图片描述
    在新弹出的窗口中点击Setup。然后输入您的控制引脚。
    在这里插入图片描述
    使用调试控件,一边观察波形图。
    在这里插入图片描述
    在程序执行RGB_PIN_H();这一句之前,我用红色的线定位了此时的时间位置,执行这一句后,我用蓝色的线查看它们之间的差值,差值为0.25us。这里我的软件仿真使用的是16MHz晶振,每个机器周期为62.5ns。0.25us相当于4个机器周期。正如我上面的发送函数里面的机器周期备注一样。同理可以计算出每行代码需要花费的机器周期时间,从而准确写出驱动。
    在这里插入图片描述
    比如,我们需要0.85us的高电平时间,也就是850ns,然后实际上我们使用的晶振是12MHz。每个机器周期的时间是理论是1/12Mhz=83.3ns。那么我们就需要850/83.3=10.2个机器周期。这里取11个机器周期。根据前面我们知道电平拉高需要用去4个机器周期,因此我们还需要让高电平维持7个机器周期的时间,然后将电平拉低。以此原理,写出我们的Ws2812b_WriteByte()函数的驱动。

    4,硬件调试

    实际硬件调试时,我写了一个测试程序。我用软件调试时,波形为引脚电平拉高10个机器周期,然后拉低10个机器周期。循环动作。

    while(1)
    {
    	P33=1;//4
    	delay6NOP();//6
    	P33=0;//4
    	delay2NOP();//2+4
    }
    

    但是实际用示波器测试时,发现高电平时间和低电平时间均为3.8格*200ns/格=760ns。所以实际上每个机器周期的时间我这里是76ns左右。距离理论值83.3ns相差不多,而且ws2812每个高电平信号都可以有150ns左右的误差,因此这里按照理论计算和按照实际计算均可。我按理论值计算。

    代码链接

    上面的代码可以直接复制使用的。最近有点穷,设置5个积分,如果各位路过的大佬觉得对您有帮助,跪求各位大佬赏口饭吃。
    https://download.csdn.net/download/weixin_38476200/16163812?spm=1001.2014.3001.5501

    总结:

    提示:这里统计学习计划的总量
    这篇文章是我的第一篇真正意义上的博客开始。希望以后我也会更新很多的博客。和大家一起前进。我的qq号码是:173039613。当然,有事尽量留言就好。QQ不一定会通过。

    展开全文
  • STC15F104W PWM 调光

    2020-12-02 14:44:20
    主控MCU:STC15F104W 开关:INT0(P3.2) 下降沿触发 亮度增加:INT2(P3.4) 下降沿触发 亮度减少:INT3(P3.5) 下降沿触发 PWM输出:P3.3 **/ #include <reg51.h> #include <intrins.h> //#...

    一、原理图

    在这里插入图片描述

    二、源程序

    /**
    	主控MCU:STC15F104W
    	开关:INT0(P3.2)			下降沿触发
    	亮度增加:INT2(P3.4)		下降沿触发
    	亮度减少:INT3(P3.5)		下降沿触发
    	PWM输出:P3.3
    **/
    
    #include <reg51.h>
    #include <intrins.h>
    
    //#define FOSC 		24000000L		//晶振频率
    #define FOSC 		6000000L		//晶振频率
    
    #define MACHINE_CYCLE	(FOSC / 1000000)	//时钟震荡6次1μs
    
    #define _1US		1				//1us
    #define _50US		50				//50us
    #define _100US		100				//100us
    #define _150US		150				//150us
    #define _200US		200				//200us
    #define _250US		250				//250us
    
    sfr INT_CLKO = 0x8f;                //外部中断与时钟输出控制寄存器
    sfr AUXR = 0x8e;                    //辅助寄存器
    sfr P3M1 = 0xB1;					//P3口寄存器
    sfr P3M0 = 0xB2;
    
    signed int duty_cycle;			//占空比,0-10,带符号
    
    unsigned int init_value;	//定时器初值
    
    unsigned int count;				//定时器中断次数
    
    sbit pwm = P3 ^ 3;					//PWM输出口
    
    bit flag;						//灯开关状态
    
    
    //INT0初始化程序
    void init_int0(void)
    {
    	INT0 = 1;
    	IT0 = 1;                    //设置INT0的中断类型 (1:仅下降沿 0:上升沿和下降沿)
    	EX0 = 1;                    //使能INT0中断
    }
    
    //INT2初始化程序
    void init_int2(void)
    {
    	INT_CLKO |= 0x10;               //(EX2 = 1)使能INT2中断
    }
    //INT3初始化程序
    void init_int3(void)
    {
    	INT_CLKO |= 0x20;               //(EX3 = 1)使能INT3中断
    }
    //初始化计时值
    void set_tm0_init_value(unsigned int value) reentrant
    {
    	switch(value) {
    		case 50:
    			TL0 = (65536 - (_50US * MACHINE_CYCLE)) % 256;
    			TH0 = (65536 - _50US * MACHINE_CYCLE) / 256;
    			break;
    
    		case 100:
    			TL0 = (65536 - _100US * MACHINE_CYCLE) % 256;
    			TH0 = (65536 - _100US * MACHINE_CYCLE) / 256;
    			break;
    
    		case 150:
    			TL0 = (65536 - _150US * MACHINE_CYCLE) % 256;
    			TH0 = (65536 - _150US * MACHINE_CYCLE) / 256;
    			break;
    
    		case 200:
    			TL0 = (65536 - _200US * MACHINE_CYCLE) % 256;
    			TH0 = (65536 - _200US * MACHINE_CYCLE) / 256;
    			break;
    
    		case 250:
    			TL0 = (65536 - _250US * MACHINE_CYCLE) % 256;
    			TH0 = (65536 - _250US * MACHINE_CYCLE) / 256;
    			break;
    
    		default:
    			TL0 = (65536 - value * MACHINE_CYCLE) % 256;
    			TH0 = (65536 - value * MACHINE_CYCLE) / 256;
    			break;
    	}
    }
    
    
    //定时器0初始化程序
    /**
    	时钟周期 = 1 / FOSC = 1 / 6 MHz = 1/6us
    	机器周期 = 1 * 时钟周期 = 1/6us	(1T模式)
    	定时100us:
    	100us = 100 / (1/6) = 600机器周期
    **/
    void init_timer0(void)
    {
    	TMOD = 0x00;                   //设置定时器0为模式0(16位自动重装载)
    	set_tm0_init_value(init_value);
    	TR0 = 1;                        	//定时器0开始计时
    	ET0 = 1;                        	//使能定时器0中断
    }
    
    /**
    	频率 = 1 / 周期
    **/
    void main(void)
    {
    	P3M1 = 0x00;
    	P3M0 = 0xFF;
    	AUXR |= 0x80;                   //定时器0为1T模式
    
    	duty_cycle = 5;	//初始占空比为50%
    
    	count = 0;
    
    	init_value = 100;	//初始频率1kHz
    
    	init_int0();
    	init_int2();
    	init_int3();
    
    	init_timer0();					//定时器初始值为0.1ms,初始频率为 1 / 0.001 = 1000Hz
    
    	flag = 0;
    
    	EA = 1;
    
    
    	while(1);
    
    }
    
    //INT0中断服务程序
    void ex_int0() interrupt 0       //INT0中断入口
    {
    	EA = 0;
    
    	flag = !flag;
    
    	if(flag) {		//关灯
    		TR0 = 0;
    		ET0 = 0;
    	} else {
    		TR0 = 1;
    		ET0 = 1;
    	}
    
    	pwm = flag;
    
    	EA = 1;
    }
    //INT2中断服务程序
    void ex_int2() interrupt 10       //INT2中断入口
    {
    	EA = 0;
    
    	if(++duty_cycle > 10) {
    		duty_cycle = 10;
    	}
    
    	INT_CLKO &= 0xEF;           //若需要手动清除中断标志,可先关闭中断,此时系统会自动清除内部的中断标志
    	INT_CLKO |= 0x10;           //然后再开中断即可
    	EA = 1;
    }
    //INT3中断服务程序
    void ex_int3() interrupt 11       //INT3中断入口
    {
    	EA = 0;
    
    	if(--duty_cycle < 0) {
    		duty_cycle = 0;
    	}
    
    	INT_CLKO &= 0xDF;               //若需要手动清除中断标志,可先关闭中断,此时系统会自动清除内部的中断标志
    	INT_CLKO |= 0x20;               //然后再开中断即可
    	EA = 1;
    }
    //定时器0中断服务程序
    void tm0_isr() interrupt 1 using 1
    {
    	EA = 0;
    
    	//初始化计时值
    	
    	set_tm0_init_value(init_value);
    
    	//pwm = !pwm;
    	if(++count > 9) {
    		count = 0;
    	}
    
    	if(count < duty_cycle) {
    		pwm = 1;
    	} else {
    		pwm = 0;
    	}
    
    	EA = 1;
    }
    
    
    展开全文
  • 闲来想起老本行,看到淘宝这款单片机小巧的,也便宜,买来玩玩。刚好装了wsl,想试下在ubuntu下编译,就不用keil这个大家伙了,百度看到都是推荐sdcc,安装也不困难,...用法也简单,但是死活连不上stc15f104w,研...

      闲来想起老本行,看到淘宝这款单片机小巧的,也便宜,买来玩玩。刚好装了wsl,想试下在ubuntu下编译,就不用keil这个大家伙了,百度看到都是推荐sdcc,安装也不困难,apt-get install sdcc,然后烧写方面,百度推荐了两个,一个stcflash.py,一个gSTC-ISP,都下载了,stcflash.py是python脚本,用法也简单,但是死活连不上stc15f104w,研究了下,里面好像没有对stc15f104w有支持,也罢,转向gSTC-ISP,这个需要编译的,但是没办法,wsl的ubuntu是阉割版的,很多环境不全,因为gSTC-ISP是有界面的,因此在编译时好像要有gnome的库?没细究,有明白的可以跟我聊下哈。反正就是编译不过,没法子,我也不想装这么多库,只能放弃在linux烧写的想法了,使用windows的stc-isp来下载呗,反正绿色版...哈哈哈。但是烧写进去后,发现功能死活没反应,仅仅是一个点灯都没反应(甚至开始怀疑我是不是已经忘了C怎么写了)。怀疑点有两个,1.编译器编译出来的代码有问题。2.烧写程序有问题。一开始想着编译器这么多linux下的运行着都在用着,应该不会错的,因此开始排查烧写程序。STC-ISP有一个示例,里面有下载烧写hex的按钮,找了一个uart的示例,然后用串口工具测了下,示例竟然没问题!!!芯片正常工作。问题来了,sdcc为什么编译出来的hex有问题呢。在百度查了好久,断断续续也有一周了吧,没有什么有关的sdcc编译资料,看来受众似乎挺小的哈哈。受到打击,差点就回来windows keil的怀抱了,突然想起,keil使用要选择芯片类型,那么sdcc毫无疑问也应该要选择芯片类型的,man了以下,stc15f104w应该是用-mmcs51,但是这个选项是默认的,也就是跟这个没关系,难受,不过有目标了,应该是跟编译选项有关的,继续找资料,最后找到一个linux下的sdcc的ide,打开我的文件,编译,日志打印了这么一串

    sdcc -mmcs51 --iram-size 256 --xram-size 0 --code-size 8192  --nooverlay --noinduction --verbose --debug -V --std-sdcc89 --model-small "main.c" 

    然后继续烧写,还是失败,但是我感觉就是这里的问题了-iram-size 256 --code-size 8192,但是实际芯片的片内falsh是4K,片内sram是128,改了下:

    sdcc -mmcs51 --iram-size 128 --xram-size 0 --code-size 4096  --nooverlay --noinduction --verbose --debug -V --std-sdcc89 --model-small "main.c" 

    烧写,!!!灯闪了,好了第一步完成,嘻嘻。

    结论,百度的教程还是不太靠谱...或者也可能我选的芯片太小众...但是有效果就好,学到了。

     

    展开全文
  • STC15F104W利用RC充放电使用IO口测量外部电压.
  • STC15F104W 点亮一个LED 上手初测

    千次阅读 2019-09-11 18:11:58
    /* 工程创建MCU选取,Atmel 89C55 单片机:STC15f104W STC 15F104W 管脚 1 P3.4 2 VCC 3.8--5.5V 3 P3.5 4 GND 5 P3.0 接烧录器的TXD 6 P3.1 接烧录器的RXD 7 P3.2 8 P3.3 功...

     

     

    /*
    工程创建MCU选取,Atmel 89C55
    单片机:STC15f104W
    STC 15F104W 管脚
    1 P3.4
    2 VCC  3.8--5.5V
    3 P3.5
    4 GND
    5 P3.0 接烧录器的TXD
    6 P3.1 接烧录器的RXD
    7 P3.2
    8 P3.3
     
    功能:500M秒闪一次LED
    连接说明:LED正极串接1K 电阻接VCC,负极接到 MCU的8脚 P3.3
    */
    #include <REG51.h>
    sbit LED = P3^3;
    void DELAY_MS (unsigned int a){
        unsigned int i;
        while ( --a != 0 )    {
            for (i=0;i<=600;i++);
        }
    }
      
    void main (void) {
         while (1)    {
            LED = ~LED;
            DELAY_MS(500);
       }
    }
    

     

     

    /*
    功能:使用1号管脚 P3.4 复位引脚,点亮LED
     
     
    工程创建MCU选取,Atmel 89C55
    单片机:STC15f104W
    STC 15F104W 管脚
    1 P3.4
    2 VCC  3.8--5.5V
    3 P3.5
    4 GND
    5 P3.0 接烧录器的TXD
    6 P3.1 接烧录器的RXD
    7 P3.2
    8 P3.3
      
    功能:500M秒闪一次LED
    连接说明:LED正极串接1K 电阻接VCC,负极接到 MCU的8脚 P3.3
    */
     
    #include <REG51.h>
    sbit LED = P3^4;
    void DELAY_MS (unsigned int a){
        unsigned int i;
        while ( --a != 0 )    {
            for (i=0;i<=600;i++);
        }
    }
       
    void main (void) {
         while (1)    {
            LED = ~LED;
            DELAY_MS(500);
       }
    }

     

     

     

    转载于:https://my.oschina.net/u/3776585/blog/1617337

    展开全文
  • STC15F104W驱动彩灯.rar

    2021-03-27 20:25:03
    默认使用内部12MHz晶振,当然代码支持12-20MHz的晶振频率,已经测试过的。也支持11.0592M。
  • 宏晶官方读取STC15F104W单片机唯一ID号并用模拟串口发送显示C例程
  • stc15f104w模拟串口使用

    2018-09-08 20:46:00
    stc15f104w单片机体积小,全8个引脚完全够一般的控制使用,最小系统也就是个电路滤波----加上一个47uf电容和一个103电容即可,但因为其是一个5V单片机,供电需要使用5V左右电源。 该款单片机视乎没有...
  • 使用STC15F104W产生PWM脉冲

    千次阅读 2014-10-04 22:18:45
    最近的小项目中使用到了STC15F104W产生PWM脉冲
  • STC15F104W-35I-SOP8开发板初体验

    千次阅读 2020-03-29 11:49:35
    一、STC15F104W外观硬件及简介 精致小巧,只有8个管脚。 对应的硬件原理图和PCB图也很简单: 看完描述以后,不仅感叹,8个脚的MCU居然可以这么牛逼,厉害了! ...
  • 读取STC15F104W程序区ID号 并用软件模拟串口输出显示 (频率为18.430MHz,波特率为 38400)
  • STC15F104W开发入门及模拟串口程序 Saturday, 31. March 2018 09:42AM - beautifulzzzz 前言 最近找到一款51内核的SOP8封装的8脚单片机STC15F10x与大家分享! 1、基本介绍 下面是其一个典型应用——红外收发器实现...
  • STC15F104W单片机 这里接收机输出的是频率为50hz,周期为2ms的pwm波形,通过单片机外部中断口接收pwm信号,启用定时器/计数器对pwm高电平的持续时间进行计数。 Arduino中的pulseIn函数可以直截了当地读取pwm的值...
  • STC15F104W 使用 315/433 MHz 超再生模块发送/接收数据一、原理图二、发送端代码三、接收端代码四、接收输出波形图 一、原理图 实验所用到的 315/433 MHz 超再生模块 发送端原理图 接收端原理图 二、发送端...
  • STC15F104W流水灯程序

    2021-07-05 21:26:35
    随便写了一个流水灯程序 : #include <reg51.h>...uchar tab1[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; uchar tab2[]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe}; uchar tab3[]={0xfe,0xfd
  • #include <reg51.h> #include <intrins.h> //定义波特率常量 //BAUD = 65536 - FOSC/3/BAUDRATE/M (1T:M=1; 12T:M=12) //NOTE: (FOSC / 3 / BAUDRATE)必须大于98,(建议增加110) ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,970
精华内容 788
关键字:

stc15f104w