找回密码
 立即注册
查看: 19|回复: 2

今天对昨天的程序进行了修改,基本正常显示了,偶尔还会乱码

[复制链接]
  • 打卡等级:初来乍到
  • 打卡总天数:4
  • 最近打卡:2026-04-02 21:42:19
已绑定手机

4

主题

3

回帖

40

积分

新手上路

积分
40
发表于 昨天 21:59 | 显示全部楼层 |阅读模式
感谢昨天坛友的建议,我修改了一下程序,(增加的代码加红字体),红外遥控接收程序基本能正常显示了,偶尔还会乱码,不过很奇怪只能显示10以内的编码怎么回事?希望大神给帮忙修改一下。



#include "STC32G.h"
#include "string.h"
#include "stdio.h"
#include "intrins.h"

typedef         unsigned char        u8;
typedef         unsigned int        u16;
typedef         unsigned long        u32;

#define MAIN_Fosc        24000000UL

/****************************** 用户定义宏 ***********************************/

#define SysTick     10000       // 次/秒, 系统滴答频率, 在4000~16000之间

#define Timer0_Reload   (65536UL - ((MAIN_Fosc + SysTick/2) / SysTick))     //Timer 0 中断频率

#define DIS_DOT     0x20
#define DIS_BLACK   0x10
#define DIS_        0x11


// I2C LCD1602地址(通常为0x27或0x3F)
#define LCD_ADDR 0x27
sbit P2_1 = P2^1;
sbit P2_0 = P2^0;
// I2C引脚定义
#define SDA_PIN P2_1
#define SCL_PIN P2_0

// LCD命令定义
#define LCD_CLEAR_DISPLAY 0x01
#define LCD_RETURN_HOME 0x02
#define LCD_ENTRY_MODE_SET 0x04
#define LCD_DISPLAY_CONTROL 0x08
#define LCD_CURSOR_SHIFT 0x10
#define LCD_FUNCTION_SET 0x20
#define LCD_SET_CGRAM_ADDR 0x40
#define LCD_SET_DDRAM_ADDR 0x80

bit B_1ms;          //1ms标志

u8  cnt_1ms;        //1ms基本计时

/*************  红外接收程序变量声明    **************/
sbit    P_IR_RX = P3^5;         //定义红外接收输入IO口

u8  IR_SampleCnt;       //采样计数
u8  IR_BitCnt;          //编码位数
u8  IR_UserH;           //用户码(地址)高字节
u8  IR_UserL;           //用户码(地址)低字节
u8  IR_data;            //数据原码
u8  IR_DataShit;        //数据移位

bit P_IR_RX_temp;       //Last sample
bit B_IR_Sync;          //已收到同步标志
bit B_IR_Press;         //红外接收标志
u8  IR_code;            //红外键码
u16 UserCode;           //用户码

/*************  本地函数声明    **************/

// 延时函数
void delay_us(unsigned int us) {
    while(us--) {
        _nop_();
        _nop_();
        _nop_();
        _nop_();
    }
}

void delay_ms(unsigned int ms) {
    unsigned int i, j;
    for(i = 0; i < ms; i++) {
        for(j = 0; j < 1000; j++) {
            _nop_();
        }
    }
}

// I2C起始信号
void I2C_Start() {
    SDA_PIN = 1;
    SCL_PIN = 1;
    delay_us(5);
    SDA_PIN = 0;
    delay_us(5);
    SCL_PIN = 0;
}

// I2C停止信号
void I2C_Stop() {
    SDA_PIN = 0;
    SCL_PIN = 1;
    delay_us(5);
    SDA_PIN = 1;
    delay_us(5);
}

// I2C发送应答信号
void I2C_Ack() {
    SDA_PIN = 0;
    SCL_PIN = 1;
    delay_us(5);
    SCL_PIN = 0;
    SDA_PIN = 1;
}

// I2C发送非应答信号
void I2C_NAck() {
    SDA_PIN = 1;
    SCL_PIN = 1;
    delay_us(5);
    SCL_PIN = 0;
    SDA_PIN = 1;
}

// I2C检测应答信号
bit I2C_CheckAck() {
    bit ack;
    SDA_PIN = 1;
    SCL_PIN = 1;
    delay_us(5);
    ack = SDA_PIN;
    SCL_PIN = 0;
    delay_us(5);
    return ack;
}

// I2C发送一个字节
void I2C_SendByte(unsigned char dat) {
    unsigned char i;
    for(i = 0; i < 8; i++) {
        SDA_PIN = (dat & 0x80) ? 1 : 0;
        dat <<= 1;
        SCL_PIN = 1;
        delay_us(5);
        SCL_PIN = 0;
        delay_us(5);
    }
    I2C_CheckAck();
}

// I2C接收一个字节
unsigned char I2C_RecvByte() {
    unsigned char i, dat = 0;
    SDA_PIN = 1;
    for(i = 0; i < 8; i++) {
        SCL_PIN = 1;
        delay_us(5);
        dat <<= 1;
        if(SDA_PIN) dat |= 0x01;
        SCL_PIN = 0;
        delay_us(5);
    }
    return dat;
}

// 向LCD发送命令或数据
void LCD_Send(unsigned char dta, bit rs) {
    unsigned char high, low;
   
    // 拆分4位数据
    high = dta & 0xF0;
    low = (dta << 4) & 0xF0;
   
    I2C_Start();
    I2C_SendByte(LCD_ADDR << 1);
   
    // 发送高4位
    I2C_SendByte(high | 0x04 | (rs ? 0x01 : 0x00));  // EN=1, RS=rs
    I2C_SendByte(high | (rs ? 0x01 : 0x00));          // EN=0, RS=rs
   
    // 发送低4位
    I2C_SendByte(low | 0x04 | (rs ? 0x01 : 0x00));    // EN=1, RS=rs
    I2C_SendByte(low | (rs ? 0x01 : 0x00));           // EN=0, RS=rs
   
    I2C_Stop();
}

// LCD初始化
void LCD_Init() {
    delay_ms(50);  // 等待LCD上电稳定
   
    // 初始化I2C引脚
    P2M1 &= ~0x03;  // P2.0(SCL), P2.1(SDA) 设为推挽输出
    P2M0 |= 0x03;
   
    // 4位模式初始化序列
    LCD_Send(0x33, 0);  // 8位模式
    LCD_Send(0x32, 0);  // 8位模式
    LCD_Send(0x28, 0);  // 4位模式,2行显示,5x8点阵
   
    LCD_Send(LCD_DISPLAY_CONTROL | 0x04, 0);  // 显示开,光标关
    LCD_Send(LCD_CLEAR_DISPLAY, 0);           // 清屏
    LCD_Send(LCD_ENTRY_MODE_SET | 0x02, 0);   // 增量模式,不移位
    delay_ms(2);
}

// 在指定位置显示字符
void LCD_DisplayChar(unsigned char x, unsigned char y, unsigned char ch) {
    unsigned char addr;
    if(y == 0) addr = 0x80 + x;
    else addr = 0xC0 + x;
    LCD_Send(addr, 0);  // 设置DDRAM地址
    LCD_Send(ch, 1);    // 写入数据
}

// 显示字符串
void LCD_DisplayString(unsigned char x, unsigned char y, unsigned char *str) {
    unsigned char addr;
    if(y == 0) addr = 0x80 + x;
    else addr = 0xC0 + x;
    LCD_Send(addr, 0);  // 设置DDRAM地址
   
    while(*str != '\0') {
        LCD_Send(*str++, 1);
    }
}

// 清屏
void LCD_Clear() {
    LCD_Send(LCD_CLEAR_DISPLAY, 0);
    delay_ms(2);
}
// 背光控制函数
void LCD_Backlight(bit state) {
    I2C_Start();                          // 起始信号
    I2C_SendByte(LCD_ADDR << 1);          // 发送设备地址
    I2C_SendByte(state ? 0x08 : 0x00);    // 控制背光
    I2C_Stop();                           // 停止信号
}

// 使用示例
// LCD_Backlight(1);  // 打开背光
// LCD_Backlight(0);  // 关闭背光





/********************* 主函数 *************************/
void main(void)
{
    char Usema[16];
          char IRma[16];
    LCD_Init();
    LCD_DisplayString(0, 0, "hongwai");
    LCD_DisplayString(0, 1, "ma shu");
    WTST = 0;  //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
    EAXFR = 1; //扩展寄存器(XFR)访问使能
    CKCON = 0; //提高访问XRAM速度
    P3M1 = 0x50;   P3M0 = 0x50;   //设置P3.4、P3.6为漏极开路(实验箱加了上拉电阻到3.3V)
   
   

    AUXR = 0x80;    //Timer0 set as 1T, 16 bits timer auto-reload,
    TH0 = (u8)(Timer0_Reload / 256);
    TL0 = (u8)(Timer0_Reload % 256);
    ET0 = 1;    //Timer0 interrupt enable
    TR0 = 1;    //Tiner0 run

    cnt_1ms = SysTick / 1000;
    EA = 1;     //打开总中断
   
   
    while(1)
    {
        if(B_1ms)   //1ms到
        {
            B_1ms = 0;
            
            if(B_IR_Press)      //检测到收到红外键码
            {
                B_IR_Press = 0;
                LCD_Clear();
                                                       
                                                        sprintf(IRma,"IR_code:%4d",IR_code);
                                                         LCD_DisplayString(0, 0,IRma );
                                                        memset(IRma,0,sizeof(IRma));
                                                          sprintf(Usema,"UserCode:%4d",UserCode);
                LCD_DisplayString(0, 1,Usema );
                                                        memset(Usema,0,sizeof(Usema));
            }
        }
    }
}

#define IR_SAMPLE_TIME      (1000000UL/SysTick)     //查询时间间隔, us, 红外接收要求在60us~250us之间
#if ((IR_SAMPLE_TIME <= 250) && (IR_SAMPLE_TIME >= 60))
    #define D_IR_sample         IR_SAMPLE_TIME      //定义采样时间,在60us~250us之间
#endif

#define D_IR_SYNC_MAX       (15000/D_IR_sample) //SYNC max time
#define D_IR_SYNC_MIN       (9700 /D_IR_sample) //SYNC min time
#define D_IR_SYNC_DIVIDE    (12375/D_IR_sample) //decide data 0 or 1
#define D_IR_DATA_MAX       (3000 /D_IR_sample) //data max time
#define D_IR_DATA_MIN       (600  /D_IR_sample) //data min time
#define D_IR_DATA_DIVIDE    (1687 /D_IR_sample) //decide data 0 or 1
#define D_IR_BIT_NUMBER     32                  //bit number

//*******************************************************************************************
//**************************** IR RECEIVE MODULE ********************************************

void IR_RX_NEC(void)
{
    u8  SampleTime;

    IR_SampleCnt++;                         //Sample + 1

    F0 = P_IR_RX_temp;                      //Save Last sample status
    P_IR_RX_temp = P_IR_RX;                 //Read current status
    if(F0 && !P_IR_RX_temp)                 //Pre-sample is high,and current sample is low, so is fall edge
    {
        SampleTime = IR_SampleCnt;          //get the sample time
        IR_SampleCnt = 0;                   //Clear the sample counter

        if(SampleTime > D_IR_SYNC_MAX)     B_IR_Sync = 0;  //large the Maxim SYNC time, then error
        else if(SampleTime >= D_IR_SYNC_MIN)                    //SYNC
        {
            if(SampleTime >= D_IR_SYNC_DIVIDE)
            {
                B_IR_Sync = 1;                  //has received SYNC
                IR_BitCnt = D_IR_BIT_NUMBER;    //Load bit number
            }
        }
        else if(B_IR_Sync)                      //has received SYNC
        {
            if(SampleTime > D_IR_DATA_MAX)      B_IR_Sync=0;    //data samlpe time too large
            else
            {
                IR_DataShit >>= 1;                  //data shift right 1 bit
                if(SampleTime >= D_IR_DATA_DIVIDE)  IR_DataShit |= 0x80;    //devide data 0 or 1
                if(--IR_BitCnt == 0)                //bit number is over?
                {
                    B_IR_Sync = 0;                  //Clear SYNC
                    if(~IR_DataShit == IR_data)     //判断数据正反码
                    {
                        UserCode = ((u16)IR_UserH << 8) + IR_UserL;
                        IR_code      = IR_data;
                        B_IR_Press   = 1;           //数据有效
                    }
                }
                else if((IR_BitCnt & 7)== 0)        //one byte receive
                {
                    IR_UserL = IR_UserH;            //Save the User code high byte
                    IR_UserH = IR_data;             //Save the User code low byte
                    IR_data  = IR_DataShit;         //Save the IR data byte
                }
            }
        }
    }
}


/********************** Timer0中断函数 ************************/
void timer0 (void) interrupt 1
{
    IR_RX_NEC();
    if(--cnt_1ms == 0)
    {
        cnt_1ms = SysTick / 1000;
        B_1ms = 1;      //1ms标志
        LCD_Backlight(1);  // 打开背光
    }
}


1.jpg
2.jpg
3.jpg
4.jpg
5.jpg
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:208
  • 最近打卡:2026-04-03 00:02:01
已绑定手机

15

主题

278

回帖

1478

积分

金牌会员

DIY玩家

积分
1478
发表于 昨天 22:30 | 显示全部楼层
显示的字符需要编码
可能显示内容含没有编码的字符
真正的学徒往往怀着大师的心
回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:4
  • 最近打卡:2026-04-02 21:42:19
已绑定手机

4

主题

3

回帖

40

积分

新手上路

积分
40
发表于 昨天 22:32 | 显示全部楼层
只能显示1-9的键码,不知道什么原因
回复

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2026-4-3 05:05 , Processed in 0.106463 second(s), 53 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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