if (rptr != wptr) { UartSend(buffer[rptr++]); rptr &= 0x0f; }
时间: 2024-02-10 22:57:47 浏览: 39
这是一个简单的环形缓冲区读取操作,通过rptr和wptr两个指针实现。如果读指针rptr不等于写指针wptr,说明缓冲区中有数据可供读取。代码中使用了位运算符&来实现循环队列的效果,避免了读指针和写指针越界的问题。其中,0x0f是用来限制指针的范围,因为环形缓冲区的大小通常是固定的。UartSend()函数是用来将缓冲区中的数据发送到串口的函数。
相关问题
#include "reg51.h" #include "intrins.h" #define FOSC 11059200UL #define BRT (65536 - FOSC / 115200 / 4) sfr AUXR = 0x8e; sfr T2H = 0xd6; sfr T2L = 0xd7; sfr S2CON = 0x9a; sfr S2BUF = 0x9b; sfr IE2 = 0xaf; sfr P0M1 = 0x93; sfr P0M0 = 0x94; sfr P1M1 = 0x91; sfr P1M0 = 0x92; sfr P2M1 = 0x95; sfr P2M0 = 0x96; sfr P3M1 = 0xb1; sfr P3M0 = 0xb2; sfr P4M1 = 0xb3; sfr P4M0 = 0xb4; sfr P5M1 = 0xc9; sfr P5M0 = 0xca; bit busy; char wptr; char rptr; char buffer[16]; void Uart2Isr() interrupt 8 { if (S2CON & 0x02) { S2CON &= ~0x02; busy = 0; } if (S2CON & 0x01) { S2CON &= ~0x01; buffer[wptr++] = S2BUF; wptr &= 0x0f; } } void Uart2Init() { S2CON = 0x10; T2L = BRT; T2H = BRT >> 8; AUXR = 0x14; wptr = 0x00; rptr = 0x00; busy = 0; } void Uart2Send(char dat) { while (busy); busy = 1; S2BUF = dat; } void Uart2SendStr(char *p) { while (*p) { Uart2Send(*p++); } } void main() { P0M0 = 0x00; P0M1 = 0x00; P1M0 = 0x00; P1M1 = 0x00; P2M0 = 0x00; P2M1 = 0x00; P3M0 = 0x00; P3M1 = 0x00; P4M0 = 0x00; P4M1 = 0x00; P5M0 = 0x00; P5M1 = 0x00; Uart2Init(); IE2 = 0x01; EA = 1; Uart2SendStr("Uart Test !\r\n"); while (1) { if (rptr != wptr) { Uart2Send(buffer[rptr++]); rptr &= 0x0f; } } } 修改此程序使发送者发送字母o接收者连接的板子中端口P2.5灯开始亮其余灯灭
修改后的程序如下:
```c
#include "reg51.h"
#include "intrins.h"
#define FOSC 11059200UL
#define BRT (65536 - FOSC / 115200 / 4)
sfr AUXR = 0x8e;
sfr T2H = 0xd6;
sfr T2L = 0xd7;
sfr S2CON = 0x9a;
sfr S2BUF = 0x9b;
sfr IE2 = 0xaf;
sfr P0M1 = 0x93;
sfr P0M0 = 0x94;
sfr P1M1 = 0x91;
sfr P1M0 = 0x92;
sfr P2M1 = 0x95;
sfr P2M0 = 0x96;
sfr P3M1 = 0xb1;
sfr P3M0 = 0xb2;
sfr P4M1 = 0xb3;
sfr P4M0 = 0xb4;
sfr P5M1 = 0xc9;
sfr P5M0 = 0xca;
bit busy;
char wptr;
char rptr;
char buffer[16];
void Uart2Isr() interrupt 8 {
if (S2CON & 0x02) {
S2CON &= ~0x02;
busy = 0;
}
if (S2CON & 0x01) {
S2CON &= ~0x01;
buffer[wptr++] = S2BUF;
wptr &= 0x0f;
}
}
void Uart2Init() {
S2CON = 0x10;
T2L = BRT;
T2H = BRT >> 8;
AUXR = 0x14;
wptr = 0x00;
rptr = 0x00;
busy = 0;
}
void Uart2Send(char dat) {
while (busy);
busy = 1;
S2BUF = dat;
}
void Uart2SendStr(char *p) {
while (*p) {
Uart2Send(*p++);
}
}
void main() {
P0M0 = 0x00;
P0M1 = 0x00;
P1M0 = 0x00;
P1M1 = 0x00;
P2M0 = 0x00;
P2M1 = 0x00;
P3M0 = 0x00;
P3M1 = 0x00;
P4M0 = 0x00;
P4M1 = 0x00;
P5M0 = 0x00;
P5M1 = 0x00;
Uart2Init();
IE2 = 0x01;
EA = 1;
Uart2SendStr("Uart Test !\r\n");
while (1) {
if (rptr != wptr) {
char received = buffer[rptr++];
rptr &= 0x0f;
if (received == 'o') {
P2 = 0x20;
} else {
P2 = 0x00;
}
Uart2Send(received);
}
}
}
```
其中,修改的部分为:
```c
if (received == 'o') {
P2 = 0x20;
} else {
P2 = 0x00;
}
```
该部分代码会检测接收到的字符是否为字母'o',如果是,则点亮P2.5灯(二进制为0010 0000),否则将P2口置为0(灭灯)。
if (((f->wptr - f->rptr) & 255) < f->num) { return f->p + (f->wptr & (f->num-1)) * f->size; } return 0;
这段代码是一个缓冲区循环队列的实现。它用于判断队列是否已满,如果队列未满,则返回队列中下一个可用的写入位置。具体来说,代码首先通过计算队列中已经被占用的元素个数来判断是否还有可用的空间。((f->wptr - f->rptr) & 255)计算出队列中已经被占用的元素个数,其中255是队列的大小减1。如果队列未满,则返回下一个可用的写入位置,即f->p + (f->wptr & (f->num-1)) * f->size。这里的f->p是指队列的起始地址,f->wptr是指队列中下一个可用的写入位置,f->num是队列的大小,f->size是每个元素的大小。如果队列已满,则返回0。