找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3333|回复: 3
打印 上一主题 下一主题
收起左侧

这个串口控制蜂鸣器 我选择ASCII和16进制都试过了就是失败帮忙看看

[复制链接]
跳转到指定楼层
楼主
ID:125710 发表于 2016-7-28 17:38 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
/*一. 程序功能
由上位机发送1给单片机,蜂鸣器以400ms频率发声,发送2时以200ms频率发声,发送3时以100ms频率发声,发送4时关闭蜂鸣器.

二. 程序源码*/
#include <reg52.h>

//声明程序需要的全局变量
unsigned char flag, a, num, benum;

//声明单片机的蜂鸣器
sbit beep = P2 ^ 3;

//声明初始化函数
void init();

//主函数
void main()
{
    //初始化
    init();

    while (1)
    {
       //检测是否发生串口中断
       if (flag == 1)
       {
           //手动将flag置0,方便下次检测
           flag = 0;
           //关闭中断???为什么需要关闭总中断而不仅仅是串口中断
           EA = 0;
           //开启计数器0
           TR0 = 1;
           //根据串口接收的数据设置蜂鸣器的频率基数
           switch(a)
           {
               case 1:
                   benum = 4;
                   break;
               case 2:
                   benum = 2;
                   break;
               case 3:
                   benum = 1;
                   break;
               case 4:
                   TR0 = 0;
                   beep = 1;
           }
           //开启总中断
           EA = 1;
        }
    }
}

void init()
{
    //设置定时器1为工作方式2, 定时器0为工作方式1
    TMOD = 0x21;
    //波特率 = (2的SMOD次方/32) * (T1溢出率)                                                                     //T1溢出率 = [256 - X]*12/晶振频率
    //根据SMOD的0,1取值得到的X分别为TH1,TL1
    //波特率选取9600,晶振频率为11.0592
    TH1 = 0xfd;
    TL1 = 0xfd;
    //以50s作为计数器0的基数
    TH0 = (65536 - 50000) / 256;
    TL0 = (65536 - 50000) % 256;
    //ET1 = 1;  这里不需要开启定时器1中断,因为定时器1工作在方式2,为8位自动重装方式,进入中断也无事可做
    //启动T1定时器
    TR1 = 1;
    //开启T0定时器
    ET0 = 1;
    //TR0 = 1; TR0的初始化放在主函数的while中,从而启动T0定时器,使蜂鸣器按频率发声
    //设定串口工作方式
    //10位异步收发(8位数据), 波特率可变(由定时器溢出率控制)
    SM0 = 0;
    SM1 = 1;
    //容许串口中断
    REN = 1;
    //开启总中断
    EA = 1;
    //开启串口中断
    ES = 1;
}

void ser() interrupt 4
{
    //RI为接收中断标志位, 在方式0时, 当串行接收第8位数据结束时, 或在其他方式, 串行接收停止位的
    //中间时, 由内部硬件使RI置1, 向CPU发出中断申请, 也必须在中断服务程序中, 用软件将其清0,取消
    //此中断申请, 以方便下一次中断申请检测, 即这样才能产生下一次中断.
    //这里RI清0, 因为程序既然产生了串口中断, 肯定是收到或发送了数据, 在开始时没有发送任何数据
    //那必然是收到了数据, 此时RI会被硬件置1, 所以进入串口中断服务程序后必须由软件清0, 这样才能
    //产生下一次中断.
    RI = 0;
    //将SBUF中的数据读走给a, 这是此中断服务程序最重要的目的
    a = SBUF;
    //将串口中断标志位置1,方便主程序检测
    flag = 1;
}

void T0_timer() interrupt 1
{
    TH0 = (65536 - 50000) / 256;
    TL0 = (65536 - 50000) % 256;
    num++;
    if (num == benum)
    {
        num = 0;
        beep = ~beep;
    }
}


仿真也测试了  我在串口助手里面输入1不来米 帮忙看看
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:135415 发表于 2016-7-29 09:01 | 只看该作者
把//ET1=1注释,有要注释的没有注释
回复

使用道具 举报

板凳
ID:125710 发表于 2016-7-29 13:53 | 只看该作者
AMB 发表于 2016-7-29 09:01
把//ET1=1注释,有要注释的没有注释

效果一样的
回复

使用道具 举报

地板
ID:135498 发表于 2016-7-30 07:08 | 只看该作者
没看到读串口部分,收到的数在哪里?a的值从哪来?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表