找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 920|回复: 3
收起左侧

求助STC8G1K08单片机的红外通信问题

[复制链接]
ID:1144471 发表于 2025-2-26 20:30 | 显示全部楼层 |阅读模式
红外遥控LED代码在51单片机上能运行,但是我移植到STC8G1K08最小系统上面却没有效果,能接收到红外信号(测试过按哪个按键LED都会亮),后面代码改成按遥控器电源键LED才会亮,但是并没有亮。问题就是为什么按电源键LED没有亮?


代码如下:
#include "STC8G.h"
#include <intrins.h>
#include "IR.h"

// 定义红外数据位数
#define IR_BIT_COUNT    32   // NEC 协议包含 32 位数据

// 定义红外信号的时间参数(单位:10us)
#define TIME_HIGH_0      12  // 逻辑 0 的高电平时间(~1.125ms)
#define TIME_LOW_0       6   // 逻辑 0 的低电平时间(~0.5625ms)
#define TIME_HIGH_1      12  // 逻辑 1 的高电平时间(~0.5625ms)
#define TIME_LOW_1       18  // 逻辑 1 的低电平时间(~1.6875ms)

void Delay10us(void) {
    unsigned char i;
    i = 27;
    while (--i);
}

void Delay500ms(void)
{
    unsigned char data i,j,k;

    _nop_();
    i=4;
    j=129;
    k=119;
    do
    {
        do
        {
            while (--k);
        }   while(--j);
    }   while(--i);
}

unsigned int GetTime(void) {
    unsigned int time = 0;
    while (P32 == 0) {  // 等待低电平结束
        Delay10us();
        time++;
    }
    while (P32 == 1) {  // 等待高电平结束
        Delay10us();
        time++;
    }
    return time;
}

unsigned char IrDecodeValue(void) {
    unsigned char ir_data = 0;
    unsigned char bit_count = 0;
    unsigned int time;

    // 等待起始信号
    while (P32 == 1);
    while (P32 == 0);
    Delay10us();
    while (P32 == 1) {
        Delay10us();
        time++;
        if (time > 450) return 0xFF;  // 超过 4.5ms,返回无效值
    }

    // 读取 32 位数据
    while (bit_count < IR_BIT_COUNT) {
        while (P32 == 1) Delay10us();  // 等待高电平结束
        time = GetTime();              // 测量低电平时间

        if (time > TIME_LOW_0 && time < TIME_LOW_1) {
            ir_data <<= 1;
            ir_data |= 0;         // 逻辑 0
        } else if (time > TIME_LOW_1) {
            ir_data <<= 1;
            ir_data |= 1;         // 逻辑 1
        } else {
            return 0xFF;          // 时间异常,返回无效值
        }

        bit_count++;
    }

    return ir_data;
}

void main() {
    P1M0 = 0x00;  // 设置 P1 准双向模式
    P1M1 = 0x00;

    while (1) {
        unsigned char key = IrDecodeValue();
        if (key == 0x45) {       // 检测按键值是否为 IR_POWER (0x45)
            P12 = 1;             // 点亮 LED
            Delay500ms();        // 延时保持亮灯
            P12 = 0;             // 熄灭 LED
        }
    }
}

回复

使用道具 举报

ID:866313 发表于 2025-2-27 02:59 | 显示全部楼层
以下内容由 DeepSeek R1 生成
根据问题描述和代码分析,问题可能出在以下几个方面:
1. 数据位处理错误
原代码中使用unsigned char ir_data(8位)存储32位数据,导致高位数据丢失。应改用32位变量:
unsigned long IrDecodeValue(void) {
     unsigned long ir_data = 0;
     // ...其余代码
     // 读取32位数据时,按位存储到ir_data
     ir_data <<= 1;
     ir_data |= (当前位值);
     // ...
     return (ir_data >> 8) & 0xFF; // 返回数据码(假设第三字节)
}2. 时间阈值与延时函数不匹配
STC8G1K08默认使用24MHz时钟(1T模式),而传统51多为12MHz(12T模式)。原Delay10us在24MHz下实际延时可能过短。需重新校准:
void Delay10us(void) {
     unsigned char i = 24; // 调整i的值,用示波器校准
     while (--i);
}3. 电平检测逻辑错误
NEC协议中,逻辑0/1由高电平时间决定,而非低电平。应修改GetTime函数以测量高电平持续时间:
unsigned int GetHighTime(void) {
     unsigned int time = 0;
     while (P32 == 1) { // 测量高电平时间
         Delay10us();
         time++;
         if(time > 1000) break; // 超时退出
     }
     return time;
}4. 未正确处理引导码
原代码未正确检测9ms低电平+4.5ms高电平的引导码。需添加引导码验证:
// 检测引导码
while (P32 == 1); // 等待高电平结束
unsigned int low_time = GetTime(); // 测量低电平时间
if (low_time < 800 || low_time > 1000) return 0xFF; // 非引导码

unsigned int high_time = GetTime(); // 测量高电平时间
if (high_time < 400 || high_time > 500) return 0xFF; // 非引导码5. 引脚配置问题
确保P3.2(红外输入)和P1.2(LED)配置正确:
void main() {
     P1M0 = 0x00; // P1准双向
     P1M1 = 0x00;
     P3M0 &= ~0x04; // P3.2准双向或高阻输入
     P3M1 &= ~0x04;
     // ...其余代码
}修正后的示例代码 #include "STC8G.h"
#include <intrins.h>

#define IR_DATA_BITS 32

void Delay10us() {
     unsigned char i = 24; // 根据24MHz调整
     while (--i);
}

unsigned int GetHighTime() {
     unsigned int time = 0;
     while (P32 == 1) {
         Delay10us();
         time++;
         if (time > 1000) break;
     }
     return time;
}

unsigned long IrDecode() {
     unsigned long data = 0;
     unsigned int time;

     // 检测引导码
     while (P32 == 1);
     time = 0;
     while (P32 == 0) { // 测量低电平时间
         Delay10us();
         time++;
         if (time > 1000) return 0;
     }
     if (time < 800) return 0; // 9ms低电平应为约900个10us

     time = 0;
     while (P32 == 1) { // 测量高电平时间
         Delay10us();
         time++;
         if (time > 500) return 0;
     }
     if (time < 400) return 0; // 4.5ms高电平应为约450个10us

     // 读取32位数据
     for (int i=0; i<IR_DATA_BITS; i++) {
         while (P32 == 0); // 等待低电平结束
         unsigned int high_time = GetHighTime();
         data <<= 1;
         if (high_time > 100) { // 高电平时间>1ms为逻辑1
             data |= 1;
         }
     }
     return data;
}

void main() {
     P1M0 = 0x00;
     P1M1 = 0x00;
     P32 = 1; // 使能P3.2上拉

     while (1) {
         unsigned long ir_code = IrDecode();
         if ((ir_code >> 8) == 0x45) { // 数据码在第三字节
             P12 = !P12; // 翻转LED
         }
     }
}调试建议
  • 使用示波器:检查红外接收头的输出波形,确认信号是否符合NEC协议。
  • 打印键值:通过串口输出接收到的键值,确认是否正确解析电源键(如0x45)。
  • 调整延时参数:根据实际时钟频率,校准Delay10us的准确性。
  • 检查硬件:确认红外接收器电源稳定,信号线连接正确(P3.2),LED电路无故障。

通过以上修正和调试步骤,应能解决STC8G1K08红外通信不响应的问题。

回复

使用道具 举报

ID:161164 发表于 2025-2-27 11:22 | 显示全部楼层
延时代码有问题
请用AIapp-ISP生成对应的晶振的延时函数
回复

使用道具 举报

ID:152164 发表于 2025-2-27 19:06 来自触屏版 | 显示全部楼层
isp软件的例程里有红外代码,用那个改嘛
回复

使用道具 举报

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

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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