找回密码
 立即注册
查看: 292|回复: 15

11F02E通过IO口控制继电器,通过串口收到数据,继电器不动作,串口通信正常

[复制链接]
  • 打卡等级:初来乍到
  • 打卡总天数:2
  • 最近打卡:2025-05-21 10:36:05
已绑定手机

1

主题

6

回帖

25

积分

新手上路

积分
25
发表于 2025-5-20 10:28:15 | 显示全部楼层 |阅读模式
#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[5];          // 接收缓冲区
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[rxIndex++] = SBUF; // 存入接收缓冲区
        SendData(SBUF);
                        
        /* 指令完整性检查 */
        if(rxIndex == 1 && rxBuffer[0] != CMD_HEAD)
            rxIndex = 0;  // 无效包头则重置
        else if(rxIndex >= 5) {
            rxIndex = 0;
            if(rxBuffer[4] == 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[1];
    BYTE action = rxBuffer[2];
        
    /* 校验检查 */
    if((rxBuffer[1] + rxBuffer[2]) != rxBuffer[3]) 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
}

回复

使用道具 举报 送花

3

主题

722

回帖

155

积分

等待验证会员

积分
155
发表于 2025-5-20 10:33:00 | 显示全部楼层
国芯AI控制继电器的实现

在当前的国芯AI系统中,控制继电器的逻辑设计需要结合STM32的 Distancetags 和串口通信的特点。以下是一段专业的国芯AI控制继电器的实现文档,供参考:

1. 目标与需求
本设计旨在通过国芯AI实现继电器的控制功能,支持全继电器(4个)的控制,同时结合串口通信,实现继电器动作的响应。

2. 基础知识回顾
STM32 Distancetags:STM32的 Distancetags 用于编码器的串口通信,支持全继电器(4个)的控制。
串口通信:通过串口通信实现继电器的动作响应,但需要结合 Distancetags 的数据进行处理。

3. 控制逻辑设计
3.1 引脚定义
以下定义了继电器的引脚:
  1. c
  2. sbit Relay1 = P3^3;        // 第1路继电器
  3. sbit Relay2 = P3^4;        // 第2路继电器
  4. sbit Relay3 = P1^2;        // 第3路继电器
  5. sbit Relay4 = P1^5;        // 第4路继电器
复制代码

3.2 系统变量定义
以下定义了系统变量:
  1. c
  2. WORD pulseTimer = 0;       // 点动计时器
  3. bit pulseActive = 0;       // 点动激活标志
  4. BYTE rxBuffer[5];          // 接收缓冲区
  5. BYTE rxIndex = 0;          // 接收索引
  6. bit cmdReady = 0;          // 指令就绪标志
复制代码

4. 控制策略
1. 串口通信:通过串口通信获取继电器的状态信息。
2. 状态转换:将串口数据转换为控制信号(如动作、不动作等)。
3. 计时与动作:根据计时器的响应时间,确定继电器的动作动作。

5. 具体实现步骤
1. 初始化:将 pulseActive 设为 0,启动计时器。
2. 串口数据获取:通过串口端口(如 CS0)读取继电器的状态信息。
3. 状态处理:将串口数据转换为控制信号。
4. 动作执行:根据控制信号,触发继电器的动作动作。
5. 计时校准:在动作完成后,启动计时器,停止计时后停止动作。

6. 具体实现代码
  1. c
  2. void controlS Relays() {
  3.     word pulseTimer = 0;
  4.     bit pulseActive = 0;
  5.    
  6.     // 串口通信部分
  7.     while ( ]; {  // 需要定义串口通信的循环条件
  8.    
  9.         // 串口读取数据
  10.         byte data = serialRead();
  11.         
  12.         // 状态转换
  13.         if (data == 0) {  // 不动作
  14.             cmdReady = 1;
  15.         } else if (data == 1) {  // 动作
  16.             cmdReady = 0;
  17.         }
  18.         
  19.         // 线程校准
  20.         pulseTimer = pulseTimer + 1;
  21.         pulseActive = pulseActive & ~(1 > 8));
  22.         
  23.         // 线程停止
  24.         if (cmdReady) {
  25.             serialWrite(0, 0);
  26.             serialWrite(0, 0);
  27.             break;
  28.         }
  29.     }
  30.    
  31.     // 退出循环
  32.     while ( ]; {  // 需要定义循环的退出条件
  33.         // 可以使用 break 或 continue 来退出循环
  34.     }
  35. }
复制代码

7. 注意事项
串口通信的安全性:确保串口通信的端口开放和关闭符合安全规范。
计时器的准确性:确保计时器的计时周期和计时数符合要求。
状态转换的准确性:确保串口数据的转换与控制信号的一致性。

以上是国芯AI控制继电器的实现文档,希望对您有所帮助!

[本文内容由国芯人工智能辅助生成,仅供参考]
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:444
  • 最近打卡:2025-06-16 09:26:42
已绑定手机

39

主题

2057

回帖

7066

积分

论坛元老

积分
7066
发表于 2025-5-20 11:06:23 | 显示全部楼层
这种问题最好提供相关的原理图,此外可先断开继电器电路,用示波器直接测量IO口电平试试。
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:468
  • 最近打卡:2025-06-16 07:06:57
已绑定手机

79

主题

5131

回帖

9138

积分

超级版主

DebugLab

积分
9138
发表于 2025-5-20 11:22:48 | 显示全部楼层
先测量IO是否有输出,再检查IO到继电器的电路,建议上传原理图
DebugLab
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:2
  • 最近打卡:2025-05-21 10:36:05
已绑定手机

1

主题

6

回帖

25

积分

新手上路

积分
25
发表于 2025-5-20 14:06:43 | 显示全部楼层
这是其中的一路继电器端的原理图
截图202505201406271313.jpg
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:2
  • 最近打卡:2025-05-21 10:36:05
已绑定手机

1

主题

6

回帖

25

积分

新手上路

积分
25
发表于 2025-5-20 14:08:10 | 显示全部楼层
乘风*** 发表于 2025-5-20 11:06
这种问题最好提供相关的原理图,此外可先断开继电器电路,用示波器直接测量IO口电平试试。 ...

把后面的和IO口连接的电阻和发光二极管删卸掉了,IO一直是高电平没变化
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:2
  • 最近打卡:2025-05-21 10:36:05
已绑定手机

1

主题

6

回帖

25

积分

新手上路

积分
25
发表于 2025-5-20 14:09:04 | 显示全部楼层
Debu*** 发表于 2025-5-20 11:22
先测量IO是否有输出,再检查IO到继电器的电路,建议上传原理图

把后面的和IO口连接的电阻和发光二极管删卸掉了,IO一直是高电平没变化
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:468
  • 最近打卡:2025-06-16 07:06:57
已绑定手机

79

主题

5131

回帖

9138

积分

超级版主

DebugLab

积分
9138
发表于 2025-5-20 14:20:42 | 显示全部楼层
注意11系列的PxMx与新型号的定义相反:
截图202505201420047950.jpg
DebugLab
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:2
  • 最近打卡:2025-05-21 10:36:05
已绑定手机

1

主题

6

回帖

25

积分

新手上路

积分
25
发表于 2025-5-20 14:54:07 | 显示全部楼层
Debu*** 发表于 2025-5-20 14:20
注意11系列的PxMx与新型号的定义相反:

可以看下最开始的帖子,我的代码就是这样写的。

点评

直接操作IO呢 P33=0 P33=1 这样  详情 回复 发表于 2025-5-20 16:31
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:468
  • 最近打卡:2025-06-16 07:06:57
已绑定手机

79

主题

5131

回帖

9138

积分

超级版主

DebugLab

积分
9138
发表于 2025-5-20 16:31:20 | 显示全部楼层
Ritc*** 发表于 2025-5-20 14:54
可以看下最开始的帖子,我的代码就是这样写的。

直接操作IO呢
P33=0
P33=1
这样
DebugLab
回复 支持 反对

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2025-6-16 13:21 , Processed in 0.342191 second(s), 109 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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