打印
[51单片机]

好书推荐《51单片机轻松入门(C语言版)—基于STC15W4K系列》

[复制链接]
楼主: 无量寿经
手机看帖
扫描二维码
随时随地手机跟帖
21
无量寿经|  楼主 | 2015-10-15 22:22 | 只看该作者 |只看大图 回帖奖励 |倒序浏览
《51单片机轻松入门-基于STC15W4K系列》内容节选:定时器0作计数器使用实验。
例3.3  使用T0作计数器对外部信号计数,计数值用P0口的LED显示出来。本例使用第一章介绍的二极管闪烁发光的实例在1号单片机P5.4输出的低频脉冲信号作为2号单片机T0(P3.4)引脚计数脉冲输入,有脉冲信号输入后从P0口就可以看到LED按二进制递增规律亮灭变化。
#include "STC15W4K.H"       // include称为文件包含命令,后面引号中内容称为头文件
void port_mode()            // 端口模式
{    // 同第一章流水灯程序
}
void main()
{  
    unsigned char DispBuf;
    port_mode();            // 所有IO口设为准双向弱上拉方式。
    P0=0xff;                // 关闭P0口接的所有灯
    TMOD=0x05;              // 确定计数工作模式为T0_16位计数,不需要重装。
    TR0=1;                  // 计数器T0开始运行
    for(;;)
    {
        DispBuf=TL0;
        P0=~DispBuf;
    }
}


使用特权

评论回复
22
无量寿经|  楼主 | 2015-10-20 22:09 | 只看该作者
51单片机轻松入门-基于STC15W4K系列》内容节选:定时器0作计数器使用实验。
例3.3  使用T0作计数器对外部信号计数,计数值用P0口的LED显示出来。本例使用第一章介绍的二极管闪烁发光的实例在1号单片机P5.4输出的低频脉冲信号作为2号单片机T0(P3.4)引脚计数脉冲输入,有脉冲信号输入后从P0口就可以看到LED按二进制递增规律亮灭变化。
#include "STC15W4K.H"       // include称为文件包含命令,后面引号中内容称为头文件
void port_mode()            // 端口模式
{    // 同第一章流水灯程序   
}
void main()
{   
    unsigned charDispBuf;
    port_mode();           // 所有IO口设为准双向弱上拉方式。
    P0=0xff;               // 关闭P0口接的所有灯
    TMOD=0x05;             // 确定计数工作模式为T0_16位计数,不需要重装。
    TR0=1;                 // 计数器T0开始运行
    for(;;)
    {
        DispBuf=TL0;
        P0=~DispBuf;
    }
}

使用特权

评论回复
23
无量寿经|  楼主 | 2015-10-28 22:30 | 只看该作者
《51单片机轻松入门-基于STC15W4K系列》内容节选:定时器0作计数器使用。
例3.3  使用T0作计数器对外部信号计数,计数值用P0口的LED显示出来。本例使用第一章介绍的二极管闪烁发光的实例在1号单片机P5.4输出的低频脉冲信号作为2号单片机T0(P3.4)引脚计数脉冲输入,有脉冲信号输入后从P0口就可以看到LED按二进制递增规律亮灭变化。
#include "STC15W4K.H"       // include称为文件包含命令,后面引号中内容称为头文件
void port_mode()            // 端口模式,所有IO口设为弱上拉方式
{   
     P0M1=0x00;P0M0=0x00;P1M1=0x00; P1M0=0x00;P2M1=0x00; P2M0=0x00;P3M1=0x00; P3M0=0x00;
     P4M1=0x00; P4M0=0x00;P5M1=0x00;P5M0=0x00;P6M1=0x00; P6M0=0x00;P7M1=0x00; P7M0=0x00;
}
void main()
{   
    unsigned charDispBuf;
    port_mode();           // 所有IO口设为准双向弱上拉方式。
    P0=0xff;               // 关闭P0口接的所有灯
    TMOD=0x05;             // 确定计数工作模式为T0_16位计数,不需要重装。
    TR0=1;                 // 计数器T0开始运行
    for(;;)
    {
        DispBuf=TL0;
        P0=~DispBuf;
    }
}

使用特权

评论回复
24
无量寿经|  楼主 | 2015-10-30 21:20 | 只看该作者
例3.4  使用T1作计数器对外部信号计数,计数值用P0口的LED显示出来。程序代码与例3.3相似。若使用配套实验板,需要将跳线帽P54-P34取下,用杜邦线将1号单片机P54连接到2号单片机P3.5/T1(26脚)上。
例3.5  使用T2作计数器对外部信号计数,计数值用P0口的LED显示出来。若使用配套实验板,需要用杜邦线将1号单片机P54连接到2号单片机P3.1/T2引脚(22脚)上。
void main()
{   
    unsigned charDispBuf;
    port_mode();           // 所有IO口设为准双向弱上拉方式。
    P0=0xff;               // 关闭P0口接的所有灯
    AUXR|=0x18;             // 定时器T2工作于计数方式并开始运行
    for(;;)
    {
        DispBuf=T2L;
        P0=~DispBuf;
    }
}

使用特权

评论回复
25
无量寿经|  楼主 | 2015-11-3 21:55 | 只看该作者
例3.6  使用T3作计数器对外部信号计数,计数值用P0口的LED显示出来,本实验需要用杜邦线将1号单片机P54连接到2号单片机P0.5/ T3引脚(6脚)上。主要代码如下:
T4T3M|=0x0c;            // 定时器T3工作于计数方式并开始运行
for(;;)
{
        DispBuf=T3L;
        P0=~DispBuf;
}
例3.7  使用T4作计数器对外部信号计数,计数值用P0口的LED显示出来,本实验需要用杜邦线将1号单片机P54连接到2号单片机T4/P0.7引脚(8脚)上。主要代码如下:
T4T3M|=0xc0;            // 定时器T4工作于计数方式并开始运行
for(;;)
{
        DispBuf=T4L;
        P0=~DispBuf;
}

使用特权

评论回复
26
无量寿经|  楼主 | 2015-11-4 21:34 | 只看该作者
多路可编程时钟输出。

例3.8  假设R/C时钟频率Fosc=11.0592MHz,设计程序实现6路时钟输出口输出100Hz~11.0592MHz频率范围的信号。实验代码如下:
// 功能:输出P5.4(MCLKO)——11.0592MHz
//       输出P3.5(T0_CLKO)——5M
//       输出P3.4(T1_CLKO)——38.4KHz
//       输出P3.0(T2_CLKO)——500Hz
//       输出P0.4(T3_CLKO)——200Hz
//       输出P0.6(T4_CLKO)——100Hz
#include"STC15W4K.H"           // 包含 "STC15W4K.H"寄存器定义头文件
#defineFOSC 11059200L          // 假设振荡时钟为11.0592MHz
#defineF5MHz (65536-11059200/2/5000000)   //5MHz
#defineF38_4KHz (65536-11059200/2/38400)  //38.4KHz
#defineF500Hz (65536-11059200/2/500)      //500Hz
#defineF200Hz (65536-11059200/2/200)      //200Hz
#defineF100Hz (65536-11059200/2/100)      //100Hz
voidmain(void)
{
    port_mode();      // 所有IO口设为准双向弱上拉方式。
//*****************  设置主时钟输出,不分频*****************   
    CLK_DIV = 0x40;     // 当使用内部R/C时钟时,R/C时钟频率要求不大于12MHz。
//*****************设置T0和T1时钟输出 *************************
    TMOD = 0x00;        // T0和T1工作在方式0,16位自动重装计数器
    AUXR = AUXR | 0x80;      // T0工作在1T模式(建议使用1T模式,高低频率都方便输出)
    AUXR = AUXR | 0x40;      // T1工作在1T模式(建议使用1T模式,高低频率都方便输出)
// 设置T0的8位自动重装计数初值,输出频率=11059200/2/74约为1MHz
    TL0 = F5MHz;
    TH0 = F5MHz>>8;     
// 设置T1的8位自动重装计数初值,输出时钟频率18432000/2/240= 38400Hz
    TL1 = F38_4KHz;
    TH1 = F38_4KHz>>8;   
    TR0 = 1;           // 启动T0开始计数,对系统时钟进行分频输出
    TR1 = 1;           // 启动T1开始计数,对系统时钟进行分频输出
    INT_CLKO =INT_CLKO|0x03;  //允许T0与T1时钟输出
//*****************设置T2时钟输出*************************
    AUXR = AUXR | 0x04; // T2工作在1T模式(建议使用1T模式,高低频率都方便输出)
    T2L = F500Hz;       // 设置T2重装时间常数的低字节
    T2H = F500Hz>>8;    // 设置T2重装时间常数的高字节     
    AUXR = AUXR |0x10;  // 启动定时器T2
    INT_CLKO |= 0x04;   // 允许T2时钟输出
//*****************设置T3、T4时钟输出 *************************
    T3L = F200Hz;       // 设置T3重装时间常数的低字节
    T3H = F200Hz>>8;    // 设置T3重装时间常数的高字节
    T4L = F100Hz;       // 设置T4重装时间常数的低字节
    T4H = F100Hz>>8;    // 设置T4重装时间常数的高字节
    T4T3M=0xbb;        // T3、T4工作在1T模式并立即运行(建议使用1T模式,高低频率都方便输出)
// 至此时钟已经输出,用户可以通过示波器观看到输出的时钟频率
    while(1);
}
使用VC97万用表测量输出,结果如下:P5.4(MCLKO)=11.07MHz, P3.5(T0_CLKO)=5.535MHz,P3.4(T1_CLKO)=38.44KHz,P3.0(T2_CLKO)=501Hz,P0.4(T3_CLKO)=201Hz,P0.6(T4_CLKO)=100.1Hz

使用特权

评论回复
27
无量寿经|  楼主 | 2015-11-6 22:04 | 只看该作者
《51单片机轻松入门-基于STC15W4K系列》内容节选
3.3 中断系统
3.3.1 中断系统结构图
当单片机正在处理当前一段程序时,突然出现了另一个更重要的事件需要处理,单片机可以暂停当前的程序段去执行更重要的事件对应的程序代码,当重要程序代码执行完毕后返回到原暂停程序处继续执行原来的代码,单片机暂停当前程序去执行其它程序的过程就称为中断,当正在执行重要程序代码的过程中出现了更为重要的事件时,单片机还可以暂停当前事件去执行更重要的事件的代码,称为中断嵌套,IAP15W4K58S4单片机有21个中断源,如图3-11左边部分所示,包括5个外部中断、5个片内定时器/计数器溢出中断、4个片内串行口(UART)中断、1个ADC中断、1个SPI中断、1个低电压检测中断、1个PCA中断、1个PWM中断、1个PWM异常中断、1个比较器中断。
  图3-11  IAP15W4K58S4单片机中断结构图(各开关处于默认状态)

3.3.2 操作电路图中的开关(相关寄存器介绍)

使用特权

评论回复
28
无量寿经|  楼主 | 2015-11-9 20:06 | 只看该作者
3.3.3 编写中断函数
1、中断函数格式:void  函数名() interrupt  m  [using n]
void : 返回值类型。由于中断函数是CPU响应中断时通过硬件自动调用的,因此中断函数的返回值和参数都只能是void(不能返回函数值,也不能给中断函数传递参数)。
函数名:可以随便写,只要方便自己识别此函数对应哪个中断源即可。
interrupt:指明此函数为中断专用函数。
m       :中断源编号(0~13、16~23)确定此函数对应哪一个硬件中断。
using  n:确定此中断函数使用第几组R0~R7寄存器组(n = 0~3),通常不必去做工作寄存器组设定,而由编译器自动选择,避免产生不必要的错误。
使用中断函数时应注意:
① 只要程序中开启了中断,就必须编写对应的中断函数,哪怕是空函数也必须有(空函数执行RETI中断返回指令),否则中断产生时却找不到可执行的中断函数,这样必然引起程序功能错乱或死机。
② 任何函数都不能直接调用中断函数,另外中断函数可放在程序中任何位置而不需要声明,只要产生中断,程序就能自动跳入中断函数执行。
中断函数名称典型书写格式如下。
void INT0(void) interrupt 0{}          // 外部中断0中断函数
void Timer0(void) interrupt 1{}        // 定时器T0 中断函数
void INT1(void) interrupt 2{}          // 外部中断1中断函数
void Timer1(void) interrupt 3{}        // 定时器T1中断函数
void UART1(void) interrupt 4{}        // 串行口1中断函数
void ADC(void) interrupt 5{}           // ADC中断函数
void LVD(void) interrupt 6{}           // 低电压检测LVD中断函数
void PCA(void) interrupt 7{}           // PCA中断函数
void UART2(void) interrupt 8{}         // 串行口2中断函数
void SPI(void) interrupt 9{}           // SPI通信中断函数
void INT2(void) interrupt 10{}         // 外部中断2中断函数
void INT3(void) interrupt 11{}         // 外部中断3中断函数
void Timer2(void) interrupt 12{}       // 定时器T2中断函数
void INT4(void) interrupt 16{}         // 外部中断4中断函数
void UART3(void) interrupt 17{}        // 串行口3中断函数
void UART4(void) interrupt 18{}        //串行口4中断函数
void Timer3(void) interrupt 19{}       // 定时器3中断函数
void Timer4(void) interrupt 20{}       // 定时器4中断函数
void Comparator(void) interrupt 21{}   // 比较器中断函数
void PWM(void) interrupt 22{}          // PWM中断函数
void PWMFD(void) interrupt 23{}        // PWM异常中断函数

使用特权

评论回复
29
无量寿经|  楼主 | 2015-11-12 22:32 | 只看该作者
2、从中断信号产生到中断函数执行是需要一个极为短暂时间等待的
   单片机响应中断的条件是:中断源有请求、相应的中断允许位设置为1、总中断开关接通(EA=1)、无同级或高级中断正在处理。在每个指令周期的最后一个时钟周期,CPU对内部中断源采样,并设置相应的中断标志位,CPU在下一个指令周期的最后一个时钟周期按优先级顺序查询各中断标志,如查到某个中断标志为1,将在下一个指令周期按优先级的高低顺序响应中断并进行处理,CPU响应中断时,将执行如下操作:当前正被执行的指令执行完毕,PC值被压入堆栈,现场保护,阻止同级别其它中断,将中断服务程序的入口地址装载到程序计数器PC,执行相应的中断服务程序。
对于外部中断,系统每个时钟对外部中断引脚采样1次,如果外部中断是下降沿触发,要求必须在相应的引脚维持高电平至少1个时钟,而且低电平也要持续至少一个时钟,才能确保该下降沿被检测到。同样,如果外部中断是上升沿、下降沿均可触发,则要求必须在相应的引脚维持低电平或高电平至少1个时钟,这样才能确保能够检测到该上升沿或下降沿。
3、使用中断的基本步骤
① 打开中断总开关EA和中断源对应的中断开关(操作IE与IE2寄存器)。
② 根据中断源确定中断函数名称与中断源编号(复制前面中断函数定义行即可)。
③ 单片机响应中断后,不会自动关闭中断系统。如果用户程序不希望出现中断嵌套,则必须在中断服务程序的开始处关闭中断,禁止更高优先级的中断请求中断当前的中断服务程序。
④ 中断源标志的清除,T0、T1、外中断产生的标志在进中断函数后立即被硬件清除,编程者通常可以不管,但在特殊情况下也必须由编程者将其清除,就是当某个中断执行时间很长时,可能中断程序还没执行完毕又产生了同一个中断,在这个中断程序最后一行代码执行完毕后又会从这个中断程序的开始执行,导致程序死机,因此在中断程序即将退出时必须清除相应的多次中断标志,其它中断产生的标志必须在中断程序中由软件清除,否则会不断重复引发中断,其现象也是死机。另外,定时器2、3、4和外部中断2、3、4的中断请求标志对用户不可见,CPU响应中断后,由硬件自动清除中断标志。

使用特权

评论回复
30
无量寿经|  楼主 | 2015-11-14 21:22 | 只看该作者
《51单片机轻松入门(C语言版)—基于STC15W4K系列》内容节选

3.3.4 中断程序举例
例3.10 用定时器T0实现P0.0引脚LED亮30ms灭30ms方式闪烁(使用中断方式),R/C时钟22.1184MHz。
//  预置初值 = 65536 – Fosc/12*T=65536-22.1184/12×30000 = 2800H
#include "STC15W4K.H"    // 包含"STC15W4K.H"寄存器定义头文件
sbit  P0_0=P0^0;
void main()
{
    P0=0xff;        // 关闭P1口接的所有灯
    TMOD=0x00;       // 定时器0的16位自动重装方式
    TH0=0x28;        //定时器初值2800H
    TL0=0;
    TR0=1;
    ET0=1;           // 开定时器0中断开关
    EA=1;           // 开总中断开关
    while(1);   
}
void Timer0() interrupt 1
{      
    P0_0=!P0_0;     // 执行灯亮或灭的动作
}

使用特权

评论回复
31
无量寿经|  楼主 | 2015-11-17 21:44 | 只看该作者
例3.11 用定时器T0实现P0.0引脚LED亮1秒灭1秒方式闪烁(使用中断方式),R/C时钟22.1184MHz。
#include "STC15W4K.H"    // 包含"STC15W4K.H"寄存器定义头文件
sbit LED=P0^0;
unsigned char counter;  // 软件计数器
void main()
{
    TMOD=0x01;           // 定时器0_16位计数
    TH0=0x70;            // 经计算定时20ms初值是0x7000
    TL0=0x00;
    TR0=1;               // 定时器开始运行
    ET0=1;              // 开定时器0中断开关
    EA=1;               // 开总中断开关
    while(1);
}  
void Timer0() interrupt 1
{   
    static  Count=0;   // 静态变量计数器,静态变量只在首次运行时赋值1次
    Count++;           // 每次中断计数器加1
    if(Count>=50)       // 如果计数器超过50
    {   
        LED=!LED;       // 取返P0.0
        Count=0;        //计数器清零  
    }
    TH0=0x70;          // 重装定时初值
    TL0=0x00;
}

使用特权

评论回复
32
无量寿经|  楼主 | 2015-11-23 20:33 | 只看该作者
例3.12  用定时中断长延时实现P0口2个LED亮灭,要求接在P0.0引脚上LED亮0.5秒灭0.5秒方式闪烁,接在P0.1引脚上LED亮1秒灭1秒方式闪烁,R/C时钟22.1184MHz。
#include "STC15W4K.H"    // 包含"STC15W4K.H"寄存器定义头文件
sbit LED0=P0^0;
sbit LED1=P0^1;
void main()
{
    TMOD=0x01;           // 定时器0_16位计数
    TH0=0x70;             // 经计算定时20ms初值是0x7000
    TL0=0x00;
    TR0=1;                // 定时器开始运行
    ET0=1;                // 开定时器0中断开关
    EA=1;                 // 开总中断开关
    while(1);
}  
void Timer0() interrupt 1
{   
    static  Count1=0;    // 静态变量计数器,静态变量只在首次运行时赋值1次
    static  Count2=0;   // 静态变量计数器
    Count1++;           // 每次中断计数器加1
    Count2++;            // 每次中断计数器加1
    if(Count1>=25)       // 如果计数器超过25
    {   
        LED0=!LED0;      // 取返P0.0
        Count1=0;        //计数器清零  
    }
    if(Count2>=50)       // 如果计数器超过50
    {   
        LED1=!LED1;      // 取返P0.1
        Count2=0;        //计数器清零  
    }
    TH0=0x70;           // 重装定时初值
    TL0=0x00;
}

使用特权

评论回复
33
ahlxy| | 2016-2-25 09:16 | 只看该作者
51单片机轻松入门—基于STC15W4K系列

使用特权

评论回复
34
ahljj| | 2016-2-25 09:17 | 只看该作者
51单片机轻松入门(C语言版)—基于STC15W4K系列

使用特权

评论回复
35
不想当初学者| | 2016-4-7 17:12 | 只看该作者
666666666666666666666666666666666666666666666666666666666666666666666666666666666

使用特权

评论回复
36
yy184911008| | 2016-4-8 09:34 | 只看该作者
51单片机轻松入门(C语言版)—基于STC15W4K系列

使用特权

评论回复
37
兰四| | 2016-7-19 13:06 | 只看该作者
很想看看

使用特权

评论回复
38
zjvskn| | 2016-8-30 23:20 | 只看该作者
很好的书

使用特权

评论回复
39
JobShare| | 2016-10-20 09:36 | 只看该作者
被禁了      

使用特权

评论回复
40
kaixuan520| | 2018-11-19 08:39 | 只看该作者
我手上有新概念和手把手51书,但是太老旧,楼主可否送pdf版的,人穷,正版纸质买不起

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则