qadiosvm 发表于 2025-5-19 18:32:43

为什么EEPORM 数据读出来都是0啊 各位老师帮忙看下

#include <STC32G.H>
#include "intrins.h"
#include "Modbus.h"
#include "stdio.h"
unsigned char xdata EEPORM_Byte;       // 数据缓存区
       
void IapIdle()
{
    IAP_CONTR = 0;                              //关闭IAP功能
    IAP_CMD = 0;                              //清除命令寄存器
    IAP_TRIG = 0;                               //清除触发寄存器
    IAP_ADDRH = 0x80;                           //将地址设置到非IAP区域
    IAP_ADDRL = 0;
}


//读EEPORM一个字节函数
unsigned char IapRead(unsigned int addr)
{
   unsigned char dat;

    IAP_CONTR = 0x80;                           //使能IAP
    IAP_TPS = 40;                               //设置等待参数40MHz
    IAP_CMD = 1;                              //设置IAP读命令
    IAP_ADDRL = addr;                           //设置IAP低地址
    IAP_ADDRH = addr >> 8;                      //设置IAP高地址
    IAP_TRIG = 0x5a;                            //写触发命令(0x5a)
    IAP_TRIG = 0xa5;                            //写触发命令(0xa5)
    _nop_();
    dat = IAP_DATA;                           //读IAP数据
    IapIdle();                                  //关闭IAP功能

    return dat;
}

//写EEPORM一个字节函数
void IapProgram(unsigned int addr, unsigned char dat)
{
    IAP_CONTR = 0x80;                           //使能IAP
    IAP_TPS = 40;                               //设置等待参数40MHz
    IAP_CMD = 2;                              //设置IAP写命令
    IAP_ADDRL = addr;                           //设置IAP低地址
    IAP_ADDRH = addr >> 8;                      //设置IAP高地址
    IAP_DATA = dat;                           //写IAP数据
    IAP_TRIG = 0x5a;                            //写触发命令(0x5a)
    IAP_TRIG = 0xa5;                            //写触发命令(0xa5)
    _nop_();
    IapIdle();                                  //关闭IAP功能
}

//擦除EEPORM函数
void IapErase(unsigned int addr)
{
    IAP_CONTR = 0x80;                           //使能IAP
    IAP_TPS = 40;                               //设置等待参数40MHz
    IAP_CMD = 3;                              //设置IAP擦除命令
    IAP_ADDRL = addr;                           //设置IAP低地址
    IAP_ADDRH = addr >> 8;                      //设置IAP高地址
    IAP_TRIG = 0x5a;                            //写触发命令(0x5a)
    IAP_TRIG = 0xa5;                            //写触发命令(0xa5)
    _nop_();                                    //
    IapIdle();                                  //关闭IAP功能
}




//========================================================================
//                           连续读取EEPORM函数
//描述:从指定EEPORM首地址读出N个字节放在指定缓冲区
//参数:EE_addr:读出EEPORM首地址
//      *data_addr :缓存区首地址
//      len: 读取字节数量
//返回值: 无
//========================================================================
void IAP_ReadString (unsigned int EE_addr,unsigned int len)
{
        unsigned int i;
        printf("读出EEPORM字节:\r\n");
        for(i=0;i<len*2;i++)
        {
       EEPORM_Byte=IapRead(EE_addr);
   EE_addr++;
               
                printf("EEPORM_Byte[%d]:%d\r\n",i,EEPORM_Byte);

        }
}

//========================================================================
//                           读写EEPORM函数
//描述:从指定EEPORM首地址读出N个字节放在指定缓冲区 然后判断是否和寄存器数据相同 不相同写入
//参数:
//      len: 读取字节数量
//返回值: 无
//========================================================================
void EEPORM_writedat (unsigned int len)
{
        unsigned int i,j;
unsigned char write =0;                   // 写入标志位

       
       
        IAP_ReadString (0x0000,len);    //先读出EEPORM数据
        printf("判断EEPORM和寄存器是否相等:\r\n");
        for (i=0;i<len;i++)                     
                {
                        if (ModbusReg==(EEPORM_Byte|EEPORM_Byte<<8))//判断modbus寄存器是否和EEPORM数据相同
                        {
                           write=0;                                                //相同置0
                                printf("相等:\r\n");
                                printf("ModbusReg[%d]:%d\r\n",i,ModbusReg);
                                printf("EEPORM_Byte[%d]:%d\r\n",i*2,EEPORM_Byte);
                                printf("EEPORM_Byte[%d]:%d\r\n",1+i*2,EEPORM_Byte);
                               
                        }else
                                {
                                       write=1;                                                // 不相同置1
                                        printf("不相等:\r\n");
                                        printf("ModbusReg[%d]:%d\r\n",i,ModbusReg);
                                  printf("EEPORM_Byte[%d]:%d\r\n",i*2,EEPORM_Byte);
                                  printf("EEPORM_Byte[%d]:%d\r\n",1+i*2,EEPORM_Byte);
                                          break;
                                }
               
                }
               
                if (write==1)                                                 //数据不同,把数据写入EEPORM里
                {
                       IapErase(0x0000);                                       //先擦除一个扇区
                        printf("扇区擦除已完成:\r\n");
                        printf("寄存器数据写入EEPORM:\r\n");
                        for (j=0;j<len;j++)                                        // 读取Moubus寄存器数据
                                {
                                        EEPORM_Byte=ModbusReg;                        // 低字节在前
                                        EEPORM_Byte=ModbusReg>>8;                     // 高字节在后
                                        printf("EEPORM_Byte[%d]=:%d\r\n",j*2,EEPORM_Byte);
                                        printf("EEPORM_Byte[%d]=:%d\r\n",1+j*2,EEPORM_Byte);
                                        printf("ModbusReg[%d]=:%d\r\n",j,ModbusReg);
                                }
                               
               
                for (i=0;i<len*2;i++)                                           //写入数据到EEPORM
                {
                        IapProgram(0x0000,EEPORM_Byte);
                        printf("EEPORM数据已写入:\r\n");
                }                       
               
                }
}


//========================================================================
//                           上电读取EEPORM数据到寄存器函数
//描述:从指定EEPORM首地址读出N个字节放在指定缓冲区 然后传给modbus寄存器
//参数:
//      len: 读取字节数量
//返回值: 无
//========================================================================
void EEPORM_writedat_Program(unsigned int len)
{
        unsigned char i;
       
        IAP_ReadString (0x0000,len);    //先读出EEPORM数据
        printf("将EEPORM字节赋给寄存器:\r\n");
        for (i=0;i<len;i++)                        // 将EEPORM数据传给Modbus寄存器
        {
                ModbusReg=EEPORM_Byte|EEPORM_Byte<<8;
                printf("ModbusReg[%d]:%d\r\n",i,ModbusReg);
        }
}



#include <STC32G.H>
#include "mcu_led.h"
#include "modbus.h"
#include "uart.h"
#include "int_out.h"
#include "eeporm.h"
#include "stdio.h"
void main ()
{
        WTST=0;   //设置程序指令延时参数,幅值0可将CPU执行指令的速度设置为最快
        EAXSFR();   //扩展SFR(XFR)访问
        CKCON=0;    //提高访问XRAM速度
        Uart2_Init(9600,0); //串口2初始化
        EEPORM_writedat_Program(5);    //上电读取EEPORM数据到寄存器
       
        LED_GPIO_lnit();    //GOIO初始化
        Timer0_Init();      //定时器0初始化
Timer4_Init();
        Uart1_Init(9600,1); //串口1初始化
       
        GPIO_inpt();      
        EA=1;               //打开总中断







国芯人工智能 发表于 2025-5-19 18:33:00

国芯AI中IAP功能的实现与数据读取机制

在国芯AI中,IAP(IAP-Configurable Address Pages)是系统中一种特殊的内存映射结构,用于实现高带宽、高内存扩展的内存管理。以下是对IAP功能的详细分析和实现,重点介绍数据读取机制。

1. IAP功能的基本概念

IAP功能是一种自适应内存映射结构,允许系统根据需求动态扩展和收缩内存区域。其核心在于通过配置寄存器(如IAPCONTR、IAPTPS等)来控制内存的访问模式和数据读写/存储的地址范围。IAP功能主要用于提高内存访问的带宽和灵活性,同时支持数据缓存的实现。

2. IAP功能的初始化

在国芯AI中,IAP功能的初始化需要配置多个寄存器,以控制内存的访问模式和数据缓存的大小。例如:
IAPCONTR: 用于控制IAP的读写功能。当IAPCONTR设置为0时,表示IAP的功能被禁用;设置为1时,表示IAP功能被启用。
IAPTPS: 用于设置等待参数,控制IAP的读写延迟。
IAPCMD: 用于设置IAP的读写命令。

这些配置寄存器的设置是实现IAP功能的关键,其值需根据实际需求进行配置。

3. IAP读取函数的实现

在国芯AI中,IAP读取函数用于从IAP缓存中读取数据。其基本结构如下:

c
unsigned char IapRead(unsigned int addr) {
    unsigned char dat;

    IAPCONTR = 0x80;    // 设置IAP读写功能
    IAPTPS = 40;      // 设置等待参数40MHz
    IAPCMD = 1;          // 设置IAP读写命令
    IAPADDRL = addr;      // 设置IAP低地址

    dat = IAPADDRH;      // 读取IAP低地址区域的地址
    return dat;
}

4. 数据读取的分析

IAP功能的核心在于数据缓存区的实现。数据缓存区是一个自适应的内存区域,其大小根据需求动态调整。在读取函数中,数据读取是从数据缓存区读取一个字节(1个8位无符号整数)。

在读取函数中,数据缓存区的地址范围由IAPTPS和IAPCONTR控制。IAPTPS决定了IAP的读写延迟,而IAPCONTR控制IAP的功能是否启用。

5. 可能的优化与问题分析

1. IAP功能的性能优化
   IAP功能的性能主要取决于IAPTPS的设置。较低的IAPTPS会增加IAP的读写延迟,影响性能。因此,需要在配置时合理设置IAPTPS,以平衡IAP的功能和性能。

2. 数据缓存区的管理
   数据缓存区的大小需要根据实际需求动态调整。如果缓存区过小,可能会影响数据读取的效率;如果缓存区过大,可能占用过多内存空间。

3. IAP功能的兼容性
   IAP功能的实现需要与其他内存映射结构(如IAP-Memory)兼容。需要确保IAP功能的配置不会与其他功能冲突。

6. 总结

国芯AI中的IAP功能通过配置寄存器实现动态内存映射和数据缓存。IAP功能的核心在于IAPCONTR、IAPTPS和IAPCMD等配置寄存器的设置,以及IAP读写函数的实现。理解IAP功能的实现和数据读取机制是国芯AI系统设计和优化的关键。

[本文内容由国芯人工智能辅助生成,仅供参考]

qadiosvm 发表于 2025-5-19 18:33:43

老师帮忙看下,哪里设置不对吗

ercircle 发表于 2025-5-19 19:04:33

为什么要一个字节一个字节处理呢?

先测试实验箱例程18-通过串口2发送命令读写EEPROM测试程序


qadiosvm 发表于 2025-5-19 19:27:38

因为用的modbus协议,不是所以数据都放入eeprom里

qadiosvm 发表于 2025-5-19 19:28:15

ercircle 发表于 2025-5-19 19:04
为什么要一个字节一个字节处理呢?

先测试实验箱例程18-通过串口2发送命令读写EEPROM测试程序


用的modbus协议

ercircle 发表于 2025-5-19 19:43:42

qadiosvm 发表于 2025-5-19 19:27
因为用的modbus协议,不是所以数据都放入eeprom里

通讯协议和EEPROM读写不要耦合的,你可以把数据离散的缓存在一个buffer里,将这个buffer一次性更新到EEPROM嘛。

qadiosvm 发表于 2025-5-19 19:50:16

ercircle 发表于 2025-5-19 19:43
通讯协议和EEPROM读写不要耦合的,你可以把数据离散的缓存在一个buffer里,将这个buffer一次性更新到EEPR ...

主要是现在是一上电,读出来的数据都是0,我在烧录的时候把eeprom数据全部改成ff了,但是读出来还是0

ercircle 发表于 2025-5-19 19:53:14

qadiosvm 发表于 2025-5-19 19:50
主要是现在是一上电,读出来的数据都是0,我在烧录的时候把eeprom数据全部改成ff了,但是读出来还是0 ...

你用的这个代码和例程差别还是有的,建议更换下再试下。
页: [1]
查看完整版本: 为什么EEPORM 数据读出来都是0啊 各位老师帮忙看下