11F02E通过IO口控制继电器,通过串口收到数据,继电器不动作,串口通信正常
#include "reg51.h"#include "intrins.h"
typedef unsigned char BYTE;
typedef unsigned int WORD;
#define FOSC 22118400L
#define BAUD 9600
/* 指令格式定义 */
#define CMD_HEAD 0xFF // 指令头
#define CMD_TAIL 0xEE // 指令尾
#define RELAY_ALL 0x25 // 全继电器操作码
#define ACTION_OFF 0x00 // 断开动作
#define ACTION_ON 0x01 // 闭合动作
#define ACTION_PULSE 0x02// 点动动作
BYTE rxBuffer; // 接收缓冲区
BYTE rxIndex = 0; // 接收索引
bit cmdReady = 0; // 指令就绪标志
/* 继电器控制引脚定义 */
sbit Relay1 = P3^3; // 第1路继电器
sbit Relay2 = P3^4; // 第2路继电器
sbit Relay3 = P1^2; // 第3路继电器
sbit Relay4 = P1^5; // 第4路继电器
/* 定时器相关变量 */
WORD pulseTimer = 0; // 点动计时器
bit pulseActive = 0; // 点动激活标志
sfr AUXR1 = 0xA2; // STC单片机扩展寄存器
sfr P1M0 = 0x92; // 0000,0000
sfr P1M1 = 0x91; //0000,0000
sfr P3M0 = 0xB2; //0000,0000
sfr P3M1 = 0xB1; // 0000,0000
#define UART_P1 0x80 // AUXR1.7位控制UART引脚切换
bit busy;
void SendData(BYTE dat);
void UART_Init();
void ProcessCommand();
void SetRelay(BYTE relay, BYTE state);
void Timer0_Init();
/******************** 主函数 ********************/
void main() {
// P1M0 |= 0x12;//设置推挽输出
// P1M1 &= 0xED;
// P3M0 |= 0x0C;
// P3M1 &= 0xF3;
// P1M0 = 0x00;
// P1M1 = 0x00;
// P3M0 = 0x00;
// P3M1 = 0x00;
P3M0 |= 0x18; P3M1 &= ~0x18;
P1M0 |= 0x24; P1M1 &= ~0x24;
AUXR1 |= UART_P1; // 切换UART到P1.6和P1.7
UART_Init(); // 初始化串口
Timer0_Init(); // 初始化定时器0
EA = 1; // 开启总中断
while(1) {
if(cmdReady) { // 检测到完整指令
cmdReady = 0;
ProcessCommand();
}
if(pulseActive && !pulseTimer) { // 点动时间到
pulseActive = 0;
SetRelay(RELAY_ALL, ACTION_OFF); // 关闭所有继电器
}
}
}
/******************** 串口初始化 ********************/
void UART_Init() {
SCON = 0x50; // 模式1,允许接收
TMOD |= 0x20; // 定时器1模式2
TH1 = TL1 = -(FOSC/12/32/BAUD);
TR1 = 1;
ES = 1; // 启用串口中断
}
/******************** 定时器0初始化 ********************/
void Timer0_Init() {
TMOD |= 0x01; // 模式1(16位定时器)
TH0 = 0xF8; // 22.1184MHz下1ms定时
TL0 = 0xCD;
ET0 = 1; // 允许定时器0中断
TR0 = 1;
}
/******************** 串口中断服务 ********************/
void UART_ISR() interrupt 4 {
if(RI) {
RI = 0;
rxBuffer = SBUF; // 存入接收缓冲区
SendData(SBUF);
/* 指令完整性检查 */
if(rxIndex == 1 && rxBuffer != CMD_HEAD)
rxIndex = 0;// 无效包头则重置
else if(rxIndex >= 5) {
rxIndex = 0;
if(rxBuffer == CMD_TAIL) cmdReady = 1; // 有效指令
}
}
if (TI)
{
TI = 0; //Clear transmit interrupt flag
busy = 0; //Clear transmit busy flag
}
}
/******************** 定时器0中断服务 ********************/
void Timer0_ISR() interrupt 1 {
TH0 = 0xF8; // 重装初值
TL0 = 0xCD;
if(pulseTimer) pulseTimer--;
}
/******************** 继电器控制函数 ********************/
void SetRelay(BYTE relay, BYTE state) {
switch(relay) {
case 0x01: Relay1 = (state == ACTION_ON); break;
case 0x02: Relay2 = (state == ACTION_ON); break;
case 0x03: Relay3 = (state == ACTION_ON); break;
case 0x04: Relay4 = (state == ACTION_ON); break;
case RELAY_ALL: // 全继电器操作
Relay1 = (state == ACTION_ON);
Relay2 = (state == ACTION_ON);
Relay3 = (state == ACTION_ON);
Relay4 = (state == ACTION_ON);
break;
}
}
/******************** 指令处理函数 ********************/
void ProcessCommand() {
BYTE relay = rxBuffer;
BYTE action = rxBuffer;
/* 校验检查 */
if((rxBuffer + rxBuffer) != rxBuffer) return;
switch(action) {
case ACTION_OFF: // 断开
SetRelay(relay, ACTION_OFF);
break;
case ACTION_ON: // 闭合
SetRelay(relay, ACTION_ON);
break;
case ACTION_PULSE: // 点动
SetRelay(relay, ACTION_ON);
pulseTimer = 1000;// 1000ms = 1s
pulseActive = 1;
break;
}
}
void SendData(BYTE dat)
{
while (busy); //Wait for the completion of the previous data is sent
busy = 1;
SBUF = dat; //Send data to UART buffer
}
国芯AI控制继电器的实现
在当前的国芯AI系统中,控制继电器的逻辑设计需要结合STM32的 Distancetags 和串口通信的特点。以下是一段专业的国芯AI控制继电器的实现文档,供参考:
1. 目标与需求
本设计旨在通过国芯AI实现继电器的控制功能,支持全继电器(4个)的控制,同时结合串口通信,实现继电器动作的响应。
2. 基础知识回顾
STM32 Distancetags:STM32的 Distancetags 用于编码器的串口通信,支持全继电器(4个)的控制。
串口通信:通过串口通信实现继电器的动作响应,但需要结合 Distancetags 的数据进行处理。
3. 控制逻辑设计
3.1 引脚定义
以下定义了继电器的引脚:
c
sbit Relay1 = P3^3; // 第1路继电器
sbit Relay2 = P3^4; // 第2路继电器
sbit Relay3 = P1^2; // 第3路继电器
sbit Relay4 = P1^5; // 第4路继电器
3.2 系统变量定义
以下定义了系统变量:
c
WORD pulseTimer = 0; // 点动计时器
bit pulseActive = 0; // 点动激活标志
BYTE rxBuffer; // 接收缓冲区
BYTE rxIndex = 0; // 接收索引
bit cmdReady = 0; // 指令就绪标志
4. 控制策略
1. 串口通信:通过串口通信获取继电器的状态信息。
2. 状态转换:将串口数据转换为控制信号(如动作、不动作等)。
3. 计时与动作:根据计时器的响应时间,确定继电器的动作动作。
5. 具体实现步骤
1. 初始化:将 pulseActive 设为 0,启动计时器。
2. 串口数据获取:通过串口端口(如 CS0)读取继电器的状态信息。
3. 状态处理:将串口数据转换为控制信号。
4. 动作执行:根据控制信号,触发继电器的动作动作。
5. 计时校准:在动作完成后,启动计时器,停止计时后停止动作。
6. 具体实现代码
c
void controlS Relays() {
word pulseTimer = 0;
bit pulseActive = 0;
// 串口通信部分
while ( ]; {// 需要定义串口通信的循环条件
// 串口读取数据
byte data = serialRead();
// 状态转换
if (data == 0) {// 不动作
cmdReady = 1;
} else if (data == 1) {// 动作
cmdReady = 0;
}
// 线程校准
pulseTimer = pulseTimer + 1;
pulseActive = pulseActive & ~(1 > 8));
// 线程停止
if (cmdReady) {
serialWrite(0, 0);
serialWrite(0, 0);
break;
}
}
// 退出循环
while ( ]; {// 需要定义循环的退出条件
// 可以使用 break 或 continue 来退出循环
}
}
7. 注意事项
串口通信的安全性:确保串口通信的端口开放和关闭符合安全规范。
计时器的准确性:确保计时器的计时周期和计时数符合要求。
状态转换的准确性:确保串口数据的转换与控制信号的一致性。
以上是国芯AI控制继电器的实现文档,希望对您有所帮助!
[本文内容由国芯人工智能辅助生成,仅供参考] 这种问题最好提供相关的原理图,此外可先断开继电器电路,用示波器直接测量IO口电平试试。 先测量IO是否有输出,再检查IO到继电器的电路,建议上传原理图 这是其中的一路继电器端的原理图 乘风飞扬 发表于 2025-5-20 11:06
这种问题最好提供相关的原理图,此外可先断开继电器电路,用示波器直接测量IO口电平试试。 ...
把后面的和IO口连接的电阻和发光二极管删卸掉了,IO一直是高电平没变化 DebugLab 发表于 2025-5-20 11:22
先测量IO是否有输出,再检查IO到继电器的电路,建议上传原理图
把后面的和IO口连接的电阻和发光二极管删卸掉了,IO一直是高电平没变化 注意11系列的PxMx与新型号的定义相反:
DebugLab 发表于 2025-5-20 14:20
注意11系列的PxMx与新型号的定义相反:
可以看下最开始的帖子,我的代码就是这样写的。 Ritchie 发表于 2025-5-20 14:54
可以看下最开始的帖子,我的代码就是这样写的。
直接操作IO呢
P33=0
P33=1
这样
页:
[1]
2