学习记录---多个功能杂合在一起的STC15单片机程序

、、、、、、、2022年11月17日。。。。。。改

#include "STC15W0XX.H"

typedef unsigned char BYTE;
typedef unsigned int WORD;

//-----------------------------------------------
//最后一个 L      表示强制长整形,无论前面的数值是多大多小,固定长度为长整形。 具体字节数取决于编译器。
//#define FOSC    11059200L   // 晶振设置,默认使用11.0592MHz 


//#define T1MS    (65536-FOSC/1000)          //1T模式 ,定时 1毫秒
//#define T1MS    (65536-FOSC/12/1000)     //12T模式
/*
它的意思是,定时器实现1毫秒定时,求定时器的初值。
因为定时器计数65536后,就会清零,想实现特定时间定时,就要自己计算起点,也叫做初值
因为1个机器周期等于12个时钟周期,因此FOSC/12,得到的是一个机器周期的频率,
也是1秒内定时器计数的个数,再除以1000,就是1毫秒内定时器计数的个数。
想让定时器在这些个数之后清零,就要设置起点为65536-该个数。

这样就得到了65536-FOSC/12/1000

同理,想设置5毫秒定时器,65536-5*FOSC/12/1000

这样得到,想设置t毫秒定时器,65536-t*FOSC/12/1000

注意,定时器有上限,最大为65536*FOSC/12毫秒,因为一个机器周期为FOSC/12毫秒,定
时器计数最多65536次,就会溢出,从0开始计数。
---------上面是12T的模式说法----------------

------->
概括的说
假如频率            5.5692MHZ
则1S计数 5569200个数
那么1ms 计数 5569200/1000 =5569.2 个~~5569个

另外,定时器计数最大数 -> 65536 后,就会清零

所以,TH0 TL0 计数器初值 = 65536-5569=59967
------->

---------------------------------------------------------------------
第2种方法:

#define FOSC 11059200L //晶振的频率

TH=(65536-time*FOSC /12)/256

TL=(65536-time*FOSC /12)%256

time就是假设要延时的100ms(要取100000us)

FOSC 是晶振频率

注意:定时器一定要考虑晶振的频率,因为单片机最小的中断时间和频率有关系。

例如:

6MHz晶振对应的时间范围是:512us --- 16.384ms --- 131.072ms

因此,在设置时间前,一定要考虑晶振和定时器的关系。

*/

//-----------------------------------------------

//sfr P3 = 0xB0;   如果不写头文件,就要单独这样写了
//sbit 自定义名 = 寄存器名

//问题:为啥要用2个IO口检测开关门的状态呢?
sbit LED1_Open     = P3^1;
sbit LED2_Close = P3^0;

sbit Door_CloseVolt = P3^4;
sbit Door_OpenVolt  = P3^5;
sbit Check_Batvolt     = P3^3;

BYTE Door_flag;         //定义一个标志位,0 无动作,1 门打开,2门关闭
BYTE Batvlot_low_flag;        //定义电池电压低判断位 ,0 不是低压(正常电压),1 暂时假设是低压(需再次判断),2 确定是低压


//WORD count;

//-----------------------------------------------
//延时函数
void Delay1ms()        //@5.5296MHz
{
    BYTE i, j;

//    _nop_();
//    _nop_();
    i = 6;
    j = 93;
    do
    {
        while (--j);
    } while (--i);
}


void Delay200ms()        //@5.5296MHz
{
    unsigned char i, j, k;

//    _nop_();
//    _nop_();
    i = 5;
    j = 52;
    k = 195;
    do
    {
        do
        {
            while (--k);
        } while (--j);
    } while (--i);
}

void Delay2000ms()        //@5.5296MHz
{
    unsigned char i, j, k;

//    _nop_();
//    _nop_();
    i = 43;
    j = 6;
    k = 203;
    do
    {
        do
        {
            while (--k);
        } while (--j);
    } while (--i);
}

//----------------------------------------------
void main (void)
    {
//IO口配置

//初始化,对所有IO口配置成准双向口
        P0M0 = 0x00;
        P0M1 = 0x00;
        P1M0 = 0x00;
        P1M1 = 0x00;
        P2M0 = 0x00;
        P2M1 = 0x00;
        P3M0 = 0x00;
        P3M1 = 0x00;
        P4M0 = 0x00;
        P4M1 = 0x00;
        P5M0 = 0x00;
        P5M1 = 0x00;
        P6M0 = 0x00;
        P6M1 = 0x00;
        P7M0 = 0x00;
        P7M1 = 0x00;
        
/*      IO口配置成准双向口

        Pn      Pn.7    Pn.6 Pn.5 Pn.4 Pn.3 Pn.2 Pn.1 Pn.0
        PnM1    0     0     0     0    0     0      0          0    
        PnM0    0     0     0     0    0     0      0          0


//方法1:总体配置
//P3.0 配置成开漏,P3.1 配置成推挽输出

        P3M1 = 0x01;            //0000 0001
        P3M0 = 0x03;            //0000 0011
        
方法2:单独配置
P3.0 单独配置成开漏 (不考虑其他引脚)
P3M1 = 0000 0001
P3M0 = 0000 0001
-----------------
初始
P3M1 = 0000 0000
P3M0 = 0000 0000
然后
P3M1 |= 0x01
P3M1 = (P3M1 | 0x01)
    0000 0000
或    0000 0001
--------------
    0000 0001
    
P3M0 |= 0x01
P3M0 = (P3M0 | 0x01)
    0000 0000
或    0000 0001
--------------
    0000 0001    

//P3.0 单独配置成开漏
P3M1 |= 0x01;
P3M0 |= 0x01;    
    
*************************
P3.1 单独配置成推挽输出 (不考虑其他引脚)
P3M1 = 0000 0000
P3M0 = 0000 0010

然后
P3M1 &=(~0x02) 
P3M1 = (P3M1 & (~0x02))

0x02取反

    0000 0010
取反
--------------
    1111 1101

再与

    0000 0000
与   1111 1101
--------------
    0000 0000
    
P3M0 |= 0x02 
P3M0 = (P3M0 | 0x02)

    0000 0000
或   0000 0010
--------------
    0000 0010

        
//P3.2 单独配置成推挽输出
P3M1 &=(~0x02);
P3M0 |= 0x02;    

*/
//初始化
//这里使用方法1
//方法1:总体配置
//P3.0 配置成开漏,P3.1 配置成推挽输出

        P3M1 = 0x00;            //0000 0000             
        P3M0 = 0x03;            //0000 0011             

/*------------------------------------------
//定时器配置

        AUXR |= 0x80;                    //定时器0为1T模式(快) ,AUXR,辅助寄存器,BIT7置1,1I模式、置0,12T模式
    //    AUXR &= (~0x80);                //定时器0为12T模式
    //    AUXR &= 0x7f;
    
        TMOD = 0x00;                    //设置定时器为模式0(16位自动重装载)
//TH0 TL0 = 65536-(5569200/12) = 59967 = EA3F        
        TL0 = T1MS;                     //赋初值的低八位,给TL0              3F
        TH0 = T1MS >> 8;                //右移八位,就是把他的高八位取出来给TH0                       EA
        
        TR0 = 1;                        //定时器0开始计时
        ET0 = 1;                        //使能定时器0中断
        EA = 1;
*/
//------------------------------------------
//初始化
//外部中断1配置
            IT1 = 0;                    //设置INT1的中断类型 (1:仅下降沿 0:上升沿和下降沿)
            EX1 = 1;                    //使能INT1中断        

//外部中断2配置
        INT_CLKO |= 0x10;                //(EX2 = 1)使能INT2中断
//外部中断3配置        
        INT_CLKO |= 0x20;               //(EX3 = 1)使能INT3中断
//开总中断        
        EA = 1;

//初始化
//-------------------------------------------------------
//两个灯,上电亮一秒,再熄灭
        LED1_Open     = 1;    // 初始化配置 开门灯开
        LED2_Close     = 1;    // 初始化配置 关门灯开
        Delay2000ms();
        LED1_Open     = 0;    // 初始化配置 开门灯关
        LED2_Close     = 0;    // 初始化配置 关门灯关

        Door_CloseVolt     = 1;    // 初始化配置 关门信号高电平
        Door_OpenVolt     = 1;    // 初始化配置 开门信号高电平
        Check_Batvolt    = 1;    // 初始化配置 电池电压正常,高电平

//初始化        
//--------------------------------------------------------------------        
//Door_flag 是个互斥事件,不会同时发送
        Door_flag = 0;          // 初始化配置 门标志位 无动作

        Batvlot_low_flag = 0;    //初始化配置 电池电压状态, 正常,不是低压
        
//        count = 0;
// 通过读取IO口状态,判断打开灯            
        while(1)  
        {    
            if(Door_flag == 1) //表示门打开
                { 
                    //LED1_Open = 1;
                    
                    Delay1ms();
                    if(Door_OpenVolt == 0)
                        {
                            LED1_Open = 1;
                            Delay200ms();
                            LED1_Open = 0;
                        }
                    
                    Door_flag = 0;
                }

            if(Door_flag == 2) //表示门关闭
                { 
                    //LED2_Close = 1;
                    
                    Delay1ms();
                    if(Door_CloseVolt == 0)
                        {
                            LED1_Open = 1;
                            Delay200ms();
                            LED1_Open = 0;
                        }
                    
                    Door_flag = 0;
                }

            if(Batvlot_low_flag == 1)    //表示P3.3临时低压,触发INT1外部中断,进入此再次判断
                { 
                    Delay200ms();
                    if(Check_Batvolt == 0)  //延时后,确认P3.3低压,即电池进入低压状态
                        {
                            Batvlot_low_flag = 2;  //表示真的低压
                        }
                    else
                        {
                            Batvlot_low_flag = 0;    //表示不是低压,还是正常电压
                        }        
                }

            if(Batvlot_low_flag == 2)
                {
                    LED2_Close = 1;
                    Delay200ms();
                    Delay200ms();
                    LED2_Close = 0;
                    Delay200ms();
                    Delay200ms();
                }
                    
            //循环检测P3.4,P3.5口电压
            //先判断是否开门,P3.5脚是否接地
/*            if(Door_Open == 0) //根据原理图,开门,Door_open IO口 变成低电平
                {
                    Delay1ms();
                    if(Door_Open == 0)
                        {
                            LED1_Open = 1;
                        }
                }

            else
                {
                    LED1_Open = 0;
                }

           //再判断是否关门,P3.4脚是否接地
            if(Door_Close == 0) //根据原理图,开门,Door_open IO口 变成低电平
                {
                    Delay1ms();
                    if(Door_Close == 0)
                        {
                            LED2_Close = 1;
                        }
                }

            else
                {
                    LED2_Close = 0;
                }
            
*/        }
    }


//-----------------------------------------------
//这个芯片,外部中断2,3,4 只支持下降沿
//中断函数
/* Timer0 interrupt routine */
/* 
void tm0_isr() interrupt 1
{
    count++;

    if(count > 999)
        {
            count = 0;
            LED2 = ! LED2;                    //将测试口取反
        }
    
}
*/

//-----------------------------------------------

//-----------------------------------------------
//中断服务程序
//中断服务程序
void exint1() interrupt 2       //INT1中断入口-->电池低压检测
{
    Batvlot_low_flag = 1;            //INT1外部中断触发,假设电池低压情况发生
                                    //这时候,需要进入主循环进程再次检测    
}


void exint2() interrupt 10          //INT2中断入口-->关门
{
        Door_flag = 2;
        // LED1_Open     = 0;
        // LED2_Close     = 1;                     
    
}

void exint3() interrupt 11          //INT3中断入口-->开门
{
        Door_flag = 1;
         //LED1_Open     = 1;
        // LED2_Close     = 0;  
}

    
 

  • 14
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

属鼠的金牛

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

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

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

打赏作者

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

抵扣说明:

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

余额充值