找回密码
 立即注册
楼主: YangHY

第一课 序言《AI8051U的特点》

[复制链接]
  • 打卡等级:偶尔看看III
  • 打卡总天数:55
  • 最近打卡:2026-03-03 08:35:54
已绑定手机

5

主题

1092

回帖

1374

积分

金牌会员

积分
1374
发表于 2026-1-29 12:16:01 | 显示全部楼层
缺点1:奇偶校验的检错率只有50%,因为只有奇数个数据位发生变化能检测到,如果偶数个数据位发生变化则无能为力了缺点2:奇偶校验每传输一个字节都需要加一位校验位,对传输效率影响很大

程序如何实现?使用9位数据位(8位数据+1位校验)
方案1:可以利用二进制数相加的特点:
0+0=0、1+0=1、1+1=0可以看出,如果我们将一个字节的所有位相加:
有奇数个“1”的字节的和为1
·有偶数个“1”的字节的和为0

方案2:


截图202601291215592586.jpg
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:55
  • 最近打卡:2026-03-03 08:35:54
已绑定手机

5

主题

1092

回帖

1374

积分

金牌会员

积分
1374
发表于 2026-1-29 12:17:18 | 显示全部楼层
看今天的任务:
截图202601291217154773.jpg
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:55
  • 最近打卡:2026-03-03 08:35:54
已绑定手机

5

主题

1092

回帖

1374

积分

金牌会员

积分
1374
发表于 2026-1-29 12:33:08 | 显示全部楼层
我们看如何编写奇校验?

初始化只改了一句:S2CON = 0xD0;                //9位数据,可变波特率

void Uart2_Init(void)        //9600bps@24.000MHz
{
               

       
        P_SW2 |= 0x01;                          //UART2/USART2: RxD2(P4.2), TxD2(P4.3)
       
        S2CON = 0xD0;                //9位数据,可变波特率
        AUXR |= 0x04;                //定时器时钟1T模式
        T2L = 0x8F;                        //设置定时初始值
        T2H = 0xFD;                        //设置定时初始值
        AUXR |= 0x10;                //定时器2开始计时
        IE2 |= 0x01;                //使能串口2中断
       
        Rec_Num = 0;
        B_TX2_Busy = 0;
}
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:55
  • 最近打卡:2026-03-03 08:35:54
已绑定手机

5

主题

1092

回帖

1374

积分

金牌会员

积分
1374
发表于 2026-1-29 12:34:22 | 显示全部楼层
接收数据时奇校验改成:

void Uart2_Isr(void) interrupt 8
{
        u8 dat;
        if (S2CON & 0x02)        //检测串口2发送中断
        {
                S2CON &= ~0x02;        //清除串口2发送中断请求位
                B_TX2_Busy = 0;
        }
        if (S2CON & 0x01)        //检测串口2接收中断
        {
                S2CON &= ~0x01;        //清除串口2接收中断请求位
               
                dat = S2BUF;
                ACC = dat;
               
                //S2BUF
                if( S2RB8 == (!P)  )        //奇校验,S2RB8是接收到的第9位数字,如果P和S2RB8相反,则奇校验通过!
                        Rec_Dat[Rec_Num++] = dat;
        }
}

回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:55
  • 最近打卡:2026-03-03 08:35:54
已绑定手机

5

主题

1092

回帖

1374

积分

金牌会员

积分
1374
发表于 2026-1-29 12:36:25 | 显示全部楼层
发送数据改为:

void Uart2_SendStr( u8 *puts )                //串口数据发送函数
{
        u8 dat;
    for (; *puts != 0;  puts++)     //遇到停止符0结束
    {
                dat = *puts;
                ACC = dat;
                if( P )   //P=1的时候,S2TB8为0,否则为1 (对应奇校验)
                        S2TB8 = 0;
                else
                        S2TB8 = 1;
               
        S2BUF = dat;
        B_TX2_Busy = 1;
        while(B_TX2_Busy);
    }       
}
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:55
  • 最近打卡:2026-03-03 08:35:54
已绑定手机

5

主题

1092

回帖

1374

积分

金牌会员

积分
1374
发表于 2026-1-29 13:00:31 | 显示全部楼层
串口通信的超时中断
当我们在做串口接收的程序的时候,往往需要当接收到一串数据的时候需要及时的响应。但是响应的第一步
就是我们得先判断这一包数据是否已经接收完成,必须要接收完成了才能进行下一步动作;

案例一:常见的AT指令集,带固定帧尾的数据。假设我们用单片机模拟一个ESP的模块,是不是当串口发来一个"At\\n"的时候需要回应一个"OK\M\n",这个可以串口接收函数里判断结尾是不是
"\r\n",监测到这个才是结尾。

案例二:串口接收定长输出,每一包的数据都是固定的字节,接受到这个长度的数据就是这一包结束了。

案例三:每一帧的数据里包含数据长度,比如每一包数据的第一个字节是长度,长度多长后面就跟几个字节的数据。
上面的几种常见案例虽然都能实现数据的完整接收,但是在实际使用的时候数据包里有没有长度,有没有固定帧尾都不是我们做从机的时候能决定的,那我们怎么样才能用最好的办法来判断一个数据包也没有接收完成呢!答案是有的

串口超时中断。

回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:55
  • 最近打卡:2026-03-03 08:35:54
已绑定手机

5

主题

1092

回帖

1374

积分

金牌会员

积分
1374
发表于 2026-1-29 13:01:52 | 显示全部楼层
怎么使用?
截图202601291301495109.jpg
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:55
  • 最近打卡:2026-03-03 08:35:54
已绑定手机

5

主题

1092

回帖

1374

积分

金牌会员

积分
1374
发表于 2026-1-29 13:07:56 | 显示全部楼层
这个寄存器其实在我们接收的时候再打开即可,ENTO不用说肯定需要使能,ENTOI是中断,可以及时响应。SCALE的话这里为了时钟
相对准,我们选择系统时钟即可。这里需要注意如果选择1us时钟的话务必要设置IAP-TPS寄存器这里三个寄存器共同组成了一个计时器,最终的计时时间 = 1/系统时钟(单位mhz)*计时器数值,假设计时器数值为44000(OXABEO),那么UR1TOTL= OXEO;UR1TOTH=OXAB;UR1TOTE= OX0O;需要注意的是这里一定要从低位开始写,且这三个寄存器一定都要写,哪怕这个寄存器的数值是0也必须要写一次。需要注意的是这个计时器的数值不能全为0!

这个寄存器就很简单了,只有一个位,触发的时候这个位会置1,我们手动清0即可。需要注意的是这个和串口发送和接收中断共用同

一个中断向量号!
截图202601291307546860.jpg
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:55
  • 最近打卡:2026-03-03 08:35:54
已绑定手机

5

主题

1092

回帖

1374

积分

金牌会员

积分
1374
发表于 2026-1-29 13:14:21 | 显示全部楼层
有校验位:假设1个字符=1(起始位)+8.(数据位)+1(奇偶校验位)+1(停止位)=11位3.5个字符=3.5*11=38.5位 如果波特率=9600bps,则3.5个字符间隔时间为38.5/9.6=4.0104167毫秒

无校验位:假设1个字符=1(起始位)+8(数据位)+0(无校验位)+1(停止位)=10位
3.5个字符=3.5*10=35位
9600波特率下,8N1的空闲时间就是 1/9600*35 ≈3.646ms;带入公式3646= 1/22.1184*计时器数值,
得出计时器数值=87504 = 0x13b04:

截图202601291309028021.jpg
截图202601291314158684.jpg
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:55
  • 最近打卡:2026-03-03 08:35:54
已绑定手机

5

主题

1092

回帖

1374

积分

金牌会员

积分
1374
发表于 2026-1-29 13:17:35 | 显示全部楼层
超时中断的完整初始化程序:
void Uart2_Init(void)        //9600bps@24.000MHz
{
       
        P_SW2 |= 0x01;                                                //UART2/USART2: RxD2(P4.2), TxD2(P4.3)
       
        S2CON = 0x50;                //8位数据,可变波特率
        AUXR |= 0x04;                //定时器时钟1T模式
        T2L = 0x8F;                        //设置定时初始值
        T2H = 0xFD;                        //设置定时初始值
        AUXR |= 0x10;                //定时器2开始计时
        IE2 |= 0x01;                //使能串口2中断

    UR2TOCR = 0x00;          //关闭超时中断                              
    UR2TOTL = 0x04;     //比特率9600bps下8N1的                           
    UR2TOTH = 0x3b;     //空闲时间是OX13b04                          
    UR2TOTE = 0x01;   

        /*9600波特率下,8N1的空闲时间就是 1/9600*35=3.646ms;
带入公式3646= 1/22.1184*计时器数值,得出计时器
数值=87504= 0x13b04;
       
*/       
        Rec_Num = 0;
        B_TX2_Busy = 0;
        B_RX2_OK = 0;
}
回复

使用道具 举报 送花

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

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2026-6-13 11:07 , Processed in 0.074118 second(s), 80 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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