吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1811|回复: 13
收起左侧

[C&C++ 转载] C51单片机串口通信笔记

[复制链接]
Cool_Breeze 发表于 2022-4-24 21:47
本帖最后由 Cool_Breeze 于 2022-4-24 21:51 编辑

到现在还是不能完全理解串口波特率计算公式。
[C] 纯文本查看 复制代码
#include<reg52.h>
#include<intrins.h>

typedef unsigned char u8;
typedef unsigned int u16;

sbit SER   = P3^4;
sbit ORCLK = P3^5; 
sbit SRCLK = P3^6;

sbit LED3 = P2^2;
sbit LED1 = P2^0;
sbit LED2 = P2^1;

void delay(u16 i){
    while(i--);
}

// 256 - (11059200 / 12 * (2^1[2^SMOD]/32)[0.0625] / 19200(波特率))
// u8 BPS = 0XFD; // 波特率 19200

static u8 BPS = 256 - 57600 / 19200;

u8 Record[16]; // 收到数据命令缓存区
u8 RIndex = 0; // 缓冲区下标

u8 Gan[] = {0x00, 0x40, 0xff, 0x49, 0x49, 0xff, 0x40, 0x00};


// 以换行符为命令结束标志
// 有返回 1
// 无返回 0
u8 CheckActionFlag(void){
    
    u8 i;
    for (i=0; i<16; i++){
        if (Record[i] == 0X0A) return 1;
    }
    return 0;
}

// 判断字符串相等
// 相等返回 1
// 不相等返回 0
u8 Equal(const char *s1, const char *s2, u8 count){
    
    u8 i = 0;
    while(i<count){
        if (*(s1++) != *(s2++)) return 0;
        i++;
    }
    return 1;
}

// 匹配命令做出相应动作
// 成功返回 1
// 失败返回 0
u8 MatchAction(void){
    
    u8 i;
    u8 f = 0;
    if (Equal(Record, "LED1", 4)){
        LED1 = ~LED1; f = 1;
    }
    else if (Equal(Record, "LED2", 4)){
        LED2 = ~LED2; f = 1;
    }
    
    for (i=0; i<16; i++, Record[i] = 0X00); // 清空缓冲区
    RIndex = 0; // 回到开始
    return f ? 1:0;
}

// 发送字符串
void Send(const char *dat, u8 count){
    
    u8 i = 0;
    ES = 0;   // 关闭串口中断,使发送数据一次性完成
    for (i=0; i<count; i++){
        SBUF = *(dat+i);
        while (!TI);
        TI = 0;
    }
    SBUF = 0X0A;
    while (!TI);
    TI = 0;
    ES = 1;  // 开启串口中断
}

// t0计时器初始化
void Timer0Init(void){
    
    TMOD |= 0x01;
    TH0 = 0x3C;
    TL0 = 0xB0;
    ET0 = 1;
    EA  = 1;
    TR0 = 1;
}

// t1计时器初始化
void Timer1Init(void){
    
    TMOD |= 0x20; // 定时器工作方式 0010 2 : GATE 0 软件启动定时器 C/T 0 计时模式  M1 1 M0 0 工作方式 2 
    TH1 = BPS;    // 自动填充数值
    TL1 = BPS;    // 设置定时器溢出值 每溢出一次就发送一个 bit
    //ET1 = 1;    // 关闭计时器的中断,因为用不到,提高效率(开启后反而影响单片机性能)
    EA  = 1;      // 中断中开关
    TR1 = 1;      // 启动定时 1
}

// 串口初始化
void UsartInit(void){
    
    Timer1Init();
    SCON = 0X50;  // SM0 0 SM1 10位异步收发器(8位数据位)方式 1 SM2 0 REN 1 软件设置接收数据
    PCON |= 0X80; // 波特率倍增 SMOD = 1( 2 / 32 ) SMOD = 0( 2 / 64 )
    ES = 1;       // 串口中断开
    EA = 1;
}

// 向芯片发送数据
void HC595SendByte(u8 dat){
    
    u8 i;
    SRCLK = 0;
    ORCLK = 0;
    for(i=0; i<8; i++){
        SER = dat >> 7;
        dat <<= 1;
        SRCLK = 1;
        _nop_(); // wait ic move bit
        _nop_();
        SRCLK = 0;
    }
    ORCLK = 1;
    _nop_();
    _nop_();
    ORCLK = 0;
}

void main(){
    
    u8 i;
    Timer0Init();
    UsartInit();
    while (1){
        for (i=1; i<9; i++){
            switch(i){
                case 1: P0 = 0x7f;break;
                case 2: P0 = 0xbf;break;
                case 3: P0 = 0xdf;break;
                case 4: P0 = 0xef;break;
                case 5: P0 = 0xf7;break;
                case 6: P0 = 0xfb;break;
                case 7: P0 = 0xfd;break;
                case 8: P0 = 0xfe;break;
            }
            HC595SendByte(Gan[i-1]);
            delay(100);
            HC595SendByte(0x00); // off led
            delay(10);
        }
        
        if (CheckActionFlag()){
            if(MatchAction()){
                Send("OK", 2);
            }
        }
    }
}

// t0中断处理器
void Timer0B() interrupt 1{
    
    static u8 ms50 = 0;
    TH0 = 0x3C;
    TL0 = 0xB0;
    ms50++;
    if (ms50 == 20){
        ms50 = 0;
        LED3 = ~LED3;
    }
}

// 串口中断处理器
void UsartProcess() interrupt 4{
    
    if (RIndex >= 16) RIndex = 0;
    Record[RIndex] = SBUF;
    while (!RI);
    RI = 0;
    RIndex++;
}

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
wxc941112 + 1 + 1 用心讨论,共获提升!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| Cool_Breeze 发表于 2022-4-25 08:22
本帖最后由 Cool_Breeze 于 2022-4-25 08:27 编辑

清空缓冲区的时候应该关闭串口中断,避免资源竞争。如果在清空缓冲区的时候又接收到数据将会打乱缓冲区,直到下一次清空缓冲区后,从新接收到的命令数据才能匹配到。
hackerbob 发表于 2022-4-24 22:10
king100 发表于 2022-4-24 22:45
很多年前学过单片机,C语言模块化,好维护,移植性很强
bj9ye666 发表于 2022-4-25 00:01
感谢分享,三年级单片机好东西
俏缘 发表于 2022-4-25 01:00
学习了,谢谢
cuixh11 发表于 2022-4-25 08:07
感谢楼主
Wapj_Wolf 发表于 2022-4-25 08:15
谢谢楼主分享干货,学习了。
minblack3 发表于 2022-4-25 09:14
刚好在学习树莓派,进来学习学习
kisscall999 发表于 2022-4-25 09:41
不错,不错,谢谢楼主分享
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-5-16 20:30

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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