求各位大神一个代码,串口控制IO口翻转
#include <reg52.h>#include <intrins.h>
#define FOSC 11059200L // 晶振频率
#define BAUD 9600 // 波特率
/* 串口初始化函数 */
void UART_Init(void)
{
SCON = 0x50; // 8位数据,可变波特率
TMOD &= 0x0F; // 清除定时器1模式位
TMOD |= 0x20; // 设定定时器1为8位自动重装方式
TL1 = 0xFD; // 设定定时初值
TH1 = 0xFD; // 设定定时器重装值
ET1 = 0; // 禁止定时器1中断
TR1 = 1; // 启动定时器1
EA = 1; // 开启总中断
ES = 1; // 开启串口中断
}
/* 主函数 */
void main(void)
{
UART_Init();
P0 = 0xFF; // 初始化P0口,LED全灭
P1 = 0xFF; // 初始化P1口,LED全灭
while(1)
{
// 主循环保持空转,等待串口中断
}
}
/* 串口中断服务函数 */
void UART_Isr(void) interrupt 4
{
unsigned char received_char;
if (RI)
{
RI = 0; // 清除接收中断标志位
received_char = SBUF; // 读取接收到的字符
// 直接在中断函数中处理,避免函数调用问题
if(received_char >= '0' && received_char <= '9')
{
unsigned char led_index = received_char - '0';
if(led_index < 8)
{
P0 ^= (1 << led_index); // 翻转P0口的LED
}
else
{
P1 ^= (1 << (led_index - 8)); // 翻转P1口的LED
}
}
else if(received_char >= 'A' && received_char <= 'F')
{
unsigned char led_index = received_char - 'A' + 10;
P1 ^= (1 << (led_index - 8)); // 翻转P1口的LED
}
else if(received_char >= 'a' && received_char <= 'f')
{
unsigned char led_index = received_char - 'a' + 10;
P1 ^= (1 << (led_index - 8)); // 翻转P1口的LED
}
}
}
这是一个串口控制IO口的引脚,单片机型号为STC89C52
当串口发送01,02,03,04,05,06,07,08,09,0A,0B,0C,0D,0E,0F是分别控制了P0.1-0.7,P1.0-1.6的IO口翻转,当串口发送10时,P1.7IO口应该翻转的,但是单片机没有任何反应
求各位大神给一个代码能够实现当串口发送01,02,03,04,05,06,07,08,09,0A,0B,0C,0D,0E,0F,10,11,12,13,14,15,16,17,18
分别控制P0,P1,P2口的24个IO口状态翻转
你提供的代码是一个基于 8051 内核的单片机(如 STC 系列)的串口通信框架,当前已经完成了串口初始化、主函数初始化 IO 口以及中断服务函数的框架。你的需求是通过串口发送特定指令控制 IO 口(例如 P0 或 P1)的翻转(即高低电平切换)。下面我将为你补充完整的串口控制 IO 翻转的代码,并进行详细说明。
✅ 一、功能需求说明
你希望通过串口接收字符(如 'A'、'B'、'0'、'1'等),根据接收到的指令控制某个 IO 口(如 P0、P1)的电平翻转,例如:
接收到字符 'P',翻转 P0 口;
接收到字符 'Q',翻转 P1 口;
或者接收到 '0' 和 '1' 来控制某个特定 IO 的高低电平。
✅ 二、补充完整代码
以下是完整可运行的代码,基于你提供的框架,补充了串口接收处理和 IO 控制逻辑:
```c
include
include
define FOSC 11059200L // 晶振频率
define BAUD 9600 // 波特率
// 串口初始化函数
void UARTInit(void)
{
SCON = 0x50; // 8位数据,可变波特率
TMOD &= 0x0F; // 清除定时器1模式位
TMOD |= 0x20; // 设定定时器1为8位自动重装方式
TL1 = 0xFD; // 设定定时初值(对应9600波特率)
TH1 = 0xFD; // 设定定时器重装值
ET1 = 0; // 禁止定时器1中断
TR1 = 1; // 启动定时器1
EA = 1; // 开启总中断
ES = 1; // 开启串口中断
}
// 主函数
void main(void)
{
UARTInit();
P0 = 0xFF; // 初始化P0口,LED全灭(共阳)
P1 = 0xFF; // 初始化P1口,LED全灭
while(1)
{
// 主循环保持空转,等待串口中断
}
}
// 串口中断服务函数
void UARTIsr(void) interrupt 4
{
unsigned char receivedchar;
if (RI) // 接收中断标志
{
RI = 0; // 清除接收中断标志
receivedchar = SBUF;// 读取接收到的字符
// 根据接收到的字符控制IO口
switch (receivedchar)
{
case 'P': // 控制P0口翻转
P0 = ~P0;
break;
case 'Q': // 控制P1口翻转
P1 = ~P1;
break;
case '0': // 设置P0.0为低电平
P0 &= ~(1
[本文内容由国芯人工智能辅助生成,仅供参考] 估计接收解析把十六进制数据还是ascii码数据搞混了
发送的是十六进制,解析时候按照ascii码值判断 研究了好多天终于解决了
发送数据00 01 01,控制P0.0输出低电平,00 01 00控制P0.0输出高电平
发送数据00 02 01,控制P0.1输出低电平,00 02 00控制P0.1输出高电平
发送数据00 03 01,控制P0.2输出低电平,00 03 00控制P0.2输出高电平
发送数据00 04 01,控制P0.3输出低电平,00 04 00控制P0.3输出高电平
发送数据00 05 01,控制P0.4输出低电平,00 05 00控制P0.4输出高电平
发送数据00 06 01,控制P0.5输出低电平,00 06 00控制P0.5输出高电平
发送数据00 07 01,控制P0.6输出低电平,00 07 00控制P0.6输出高电平
发送数据00 08 01,控制P0.7输出低电平,00 08 00控制P0.7输出高电平
发送数据00 09 01,控制P1.0输出低电平,00 09 00控制P1.0输出高电平
发送数据00 0A 01,控制P1.1输出低电平,00 0A 00控制P1.1输出高电平
发送数据00 0B 01,控制P1.2输出低电平,00 0B 00控制P1.2输出高电平
发送数据00 0C 01,控制P1.3输出低电平,00 0C 00控制P1.3输出高电平
发送数据00 0D 01,控制P1.4输出低电平,00 0D 00控制P1.4输出高电平
发送数据00 0E 01,控制P1.5输出低电平,00 0E 00控制P1.5输出高电平
发送数据00 0F 01,控制P1.6输出低电平,00 0F 00控制P1.6输出高电平
发送数据01 01 01,控制P1.7输出低电平,01 01 00控制P1.7输出高电平
发送数据01 02 01,控制P2.0输出低电平,01 02 00控制P2.0输出高电平
发送数据01 03 01,控制P2.1输出低电平,01 03 00控制P2.1输出高电平
发送数据01 04 01,控制P2.2输出低电平,01 04 00控制P2.2输出高电平
发送数据01 05 01,控制P2.3输出低电平,01 05 00控制P2.3输出高电平
发送数据01 06 01,控制P2.4输出低电平,01 06 00控制P2.4输出高电平
发送数据01 07 01,控制P2.5输出低电平,01 07 00控制P2.5输出高电平
发送数据01 08 01,控制P2.6输出低电平,01 08 00控制P2.6输出高电平
发送数据01 09 01,控制P2.7输出低电平,01 09 00控制P2.7输出高电平
发送数据01 0A 01,控制P3.2输出低电平,01 0A 00控制P3.2输出高电平
发送数据01 0B 01,控制P3.3输出低电平,01 0B 00控制P3.3输出高电平
发送数据01 0C 01,控制P3.4输出低电平,01 0C 00控制P3.4输出高电平
发送数据01 0D 01,控制P3.5输出低电平,01 0D 00控制P3.5输出高电平
发送数据01 0E 01,控制P3.6输出低电平,01 0E 00控制P3.6输出高电平
发送数据01 0F 01,控制P3.7输出低电平,01 0F 00控制P3.7输出高电平
发送数据:
00 01 01 00 02 01 00 03 01 00 04 01 00 05 01 00 06 01 00 07 01
00 08 01 00 09 01 00 0A 01 00 0B 01 00 0C 01 00 0D 01 00 0E 01
00 0F 01 01 01 01 01 02 01 01 03 01 01 04 01 01 05 01 01 06 01
01 07 01 01 08 01 01 09 01 01 0A 01 01 0B 01 01 0C 01 01 0D 01
01 0E 01 01 0F 01
30个IO口全部输出低电平
——————————————————
发送数据:
00 01 00 00 02 00 00 03 00 00 04 00 00 05 00 00 06 00 00 07 00
00 08 00 00 09 00 00 0A 00 00 0B 00 00 0C 00 00 0D 00 00 0E 00
00 0F 00 01 01 00 01 02 00 01 03 00 01 04 00 01 05 00 01 06 00
01 07 00 01 08 00 01 09 00 01 0A 00 01 0B 00 01 0C 00 01 0D 00
01 0E 00 01 0F 00
30个IO口全部输出高电平
代码:
#include <reg52.h>
// 全局变量存储端口状态,初始都为高电平(灭)
unsigned char port_states = {0xFF, 0xFF, 0xFF, 0xFF};
void UART_Init(void)
{
SCON = 0x50; // 8位数据,可变波特率
TMOD |= 0x20; // 定时器1工作在模式2
TH1 = 0xFD; // 波特率9600 (11.0592MHz晶振)
TL1 = 0xFD;
TR1 = 1; // 启动定时器1
ES = 1; // 使能串口中断
EA = 1; // 开总中断
}
// 更新显示函数
void UpdateDisplay(void)
{
P0 = port_states;// 更新P0口
P1 = port_states;// 更新P1口
P2 = port_states;// 更新P2口
P3 = port_states;// 更新P3口
}
void main(void)
{
UART_Init();
P0 = 0xFF; // 初始P0口全灭
P1 = 0xFF; // 初始P1口全灭
P2 = 0xFF; // 初始P2口全灭
P3 = 0xFF; // 初始P3口全灭
while(1)
{
// 主循环空转,等待串口中断
}
}
void UART_Isr(void) interrupt 4
{
unsigned char received_data;
static unsigned char command_buffer; // 命令缓冲区
static unsigned char buffer_index = 0;// 缓冲区索引
unsigned char port_selector;
unsigned char pin_selector;
unsigned char port_index;
unsigned char bit_mask;
unsigned char state;// 变量声明必须在函数开头
if(RI)
{
RI = 0; // 清除接收中断标志
received_data = SBUF; // 读取接收到的数据
// 将数据存入缓冲区
command_buffer = received_data;
buffer_index++;
// 如果收到3个字节,处理命令
if(buffer_index >= 3)
{
port_selector = command_buffer; // 端口选择器
pin_selector = command_buffer; // 引脚选择器
state = command_buffer; // 状态
// 根据端口选择器和引脚选择器确定端口和位
if(port_selector == 0x00)// P0和P1口
{
if(pin_selector >= 0x01 && pin_selector <= 0x08)// P0.0-P0.7
{
port_index = 0;
bit_mask = 1 << (pin_selector - 0x01);
}
else if(pin_selector >= 0x09 && pin_selector <= 0x0F)// P1.0-P1.6
{
port_index = 1;
bit_mask = 1 << (pin_selector - 0x09);
}
else
{
buffer_index = 0;
return;
}
}
else if(port_selector == 0x01)// P1.7, P2, P3口
{
if(pin_selector == 0x01)// P1.7
{
port_index = 1;
bit_mask = 0x80;// 10000000
}
else if(pin_selector >= 0x02 && pin_selector <= 0x09)// P2.0-P2.7
{
port_index = 2;
bit_mask = 1 << (pin_selector - 0x02);
}
else if(pin_selector >= 0x0A && pin_selector <= 0x0F)// P3.2-P3.7
{
port_index = 3;
// P3.2-P3.7对应位掩码:00000100-10000000
// 0x0A->P3.2, 0x0B->P3.3, 0x0C->P3.4, 0x0D->P3.5, 0x0E->P3.6, 0x0F->P3.7
bit_mask = 1 << (pin_selector - 0x08);
}
else
{
buffer_index = 0;
return;
}
}
else
{
// 无效端口选择器,忽略
buffer_index = 0;
return;
}
// 根据第三个字节设置状态
if(state == 0x01)// 输出低电平
{
port_states &= ~bit_mask;// 对应位置0
}
else if(state == 0x00)// 输出高电平
{
port_states |= bit_mask; // 对应位置1
}
// 更新显示
UpdateDisplay();
// 重置缓冲区索引
buffer_index = 0;
}
}
} 网老四 发表于 2025-9-30 18:45
估计接收解析把十六进制数据还是ascii码数据搞混了
发送的是十六进制,解析时候按照ascii码值判断 ...
感谢大佬指点 烧录文件
页:
[1]