我想将数字存储到PIC18,然后保留它,即使电源丢失或设备复位也是如此。我认为我的编写代码部分看起来很好,只是在重置单元后它的读取部分看起来很奇怪。
我使用的是Microchip提供的以下代码。
代码:
unsigned int value;
unsigned int DEEdata = 1;
unsigned int DEEaddr = 0x04;
DataEEInit();
dataEEFlags.val = 0;
DataEEWrite(DEEdata,DEEaddr);
value = DataEERead(DEEaddr);
Nop();
printf("%d",value);
输出:1
然而,当我重置单位并且只使用阅读代码时,我总是得到255.
要阅读的代码:
DataEEInit();
value = DataEERead(DEEaddr);
printf("%d",value);
输出:255
为什么会这样?我假设可能没有保存值或读取部分不正确。谢谢!
答案 0 :(得分:1)
您正在使用的设备除了Flash之外没有内部非易失性存储器,通常用于存储代码。
我可以看到两个选项:
多年来我一直没有与PIC合作,所以不能为实现细节提供太多帮助,但我怀疑有很多例子可以从Microchip的网站上找到。
从本质上讲,你的代码不起作用的原因是因为你试图访问那些不存在的内存。如果它存在,那么界面不正确。
编辑:
我已经浏览了Microchip网站上PIC18的代码示例页面,但找不到任何用于写入程序存储器的C示例。不幸的是,看起来你必须在汇编程序中实现它。我不知道MPLAB编译器的语义,但一般情况下,如果你要内联它,它将是这样的东西:
void my_assembler_function(void)
{
// Inline assembler code, actioned via C.
asm("MOV x y");
asm("MOV y z");
}
或者,许多用于微处理器的C编译器允许您使用C函数调用调用外部.s
文件,从而使您无需内联。
我认为您可以按照我找到here的示例来实际实现您所追求的功能。
答案 1 :(得分:1)
SRAM不能用于存储非易失性数据......
SRAM会在电源循环期间丢失数据......
选项: 1.如果可用,请使用内部EEPROM。 2.通过I2C或SPI的外部EEPROM。 3. PIC18数据仿真库。
答案 2 :(得分:1)
两个功能:使用64字节缓冲区@ 8字节块写入闪存和读取/比较闪存功能。
对于器件:PIC18F46K80
头文件的填充:
#define PRGM_BUFFER_SIZE 8
#define TABLE_WRITE_SIZE 64
#define LOAD_TBL_PTR(x) { TBLPTRU = ((((x)>>8)>>8)&0xff);\
TBLPTRH = (((x) >> 8) & 0xff);\
TBLPTRL = ((x) & 0xff);\
}
写入闪光灯功能:
/******************************************************
* Function : write_block
* Input : uint16_t position in destination flash
* Global : uint8_t buffer[64] - Location of source data
* Output : None
* Description : Writes the contents of the 64 byte
* data buffer to program flash space. Only 64 bytes
* can be written at once. The process of writing
* to flash is: Erase->Write.
******************************************************/
static void write_block(uint16_t addr)
{
int r, c;
// Erase flash block first. Erases a 64 byte block at a time.
LOAD_TBL_PTR(addr);
EECON1bits.EEPGD = 1; // Point to flash program memory
EECON1bits.CFGS = 0; // Access flash memory
EECON1bits.WREN = 1; // Enable write to memory
EECON1bits.FREE = 1; // Enable Erase operation
EECON2 = 0x55;
EECON2 = 0xAA;
EECON1bits.WR = 1; // Clear the flash
asm("NOP"); // Stall
// Write buffer to internal buffer. This process writes 8 bytes at a time
// so we need to loop 8 times (8*8 = 64).)
for (r = 0; r < 8; r++)
{
LOAD_TBL_PTR((addr + (r * 8)));
for (c = 0; c < PRGM_BUFFER_SIZE; c++)
{
TABLAT = buffer[(r * 8) + c];
asm("TBLWT*+"); // Push byte and then inc to next internal buffer cell
}
// Write the block to flash
asm("TBLRD*-"); // Point back to original row
// Write internal buffer to flash
EECON1bits.EEPGD = 1; // Point to flash program memory
EECON1bits.CFGS = 0; // Access flash program memory
EECON1bits.WREN = 1; // Enable write to memory
INTCONbits.GIE = 0; // Disable interrupts
EECON2 = 0x55;
EECON2 = 0xAA;
EECON1bits.WR = 1; // Start programming flash
INTCONbits.GIE = 1; // Re-enable interrupts
EECON1bits.WREN = 0; // Disable write to memory
}
}
验证书面数据(演示闪存读取)
/******************************************************
* Function : compare_block
* Input : uint16_t position in destination flash
* Global : uint8_t buffer[64] - Location of previous written data
* Output : bool true=successful, false=did not match
* Description : Reads a 64 byte block of flash memory and
* compares it to the data found in the global buffer.
******************************************************/
static bool compare_block(uint16_t addr)
{
bool retVal = true; // succeeds
uint8_t i = 0;
INTCONbits.GIE = 0; // Disable interrupts
LOAD_TBL_PTR(addr);
for (i = 0; i < TABLE_WRITE_SIZE && retVal == true; i++)
{
asm("TBLRD*+");
if (buffer[i] != TABLAT)
retVal = false;
}
INTCONbits.GIE = 1; // Enable interrupts
return retVal;
}
此致, 布莱恩威尔切特
答案 3 :(得分:1)
这是对PIC18的解释:
/* EEPROM Read and Write Functions -- WORKING
* Used PIC18F45K22 and MPLAB and C18
* Read and Write functions work.
* EEPROM has 256 bytes of memory (256 distinct characters)
* Select "Window" -> "PIC Memory Views" -> "EE Data Memory"
* Download program to PIC18
* Hold PIC in Reset (circle arrow with pause button)
* Open EE Data Memory Tab and click "Read Device Memory" button (Top left of EE Data tab) while PIC is held in Reset
*/
这是有用的代码:
#include <p18cxxx.h>
#include <p18f45k22.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#pragma config FOSC = INTIO67, PLLCFG = OFF, PRICLKEN = ON, FCMEN = ON, PWRTEN = OFF
#pragma config BOREN = SBORDIS, BORV = 250, WDTEN = OFF, WDTPS = 2048, PBADEN = OFF, WRTD = OFF
#pragma config HFOFST = OFF, MCLRE = EXTMCLR, STVREN = ON, LVP = OFF, DEBUG = ON, CPD = OFF
void EE_Write(unsigned char addr, unsigned char value);
unsigned char EE_Read(unsigned char addr);
unsigned char test;
void main(void){
OSCTUNEbits.PLLEN = 1;
OSCCON = 0x4C; //Set to use internal clock.
OSCCON2 = 0x00; // No 4x PLL
TRISB = 0x00;
ANSELB = 0x00;
PORTB = 0x00;
EE_Write(05, 0x5A);
Delay10KTCYx(50);
test = EE_Read(05);
Delay10KTCYx(50);
PORTB = 0xFF;
Delay10KTCYx(50);
PORTB = 0x00;
}
void EE_Write(unsigned char addr, unsigned char value)
{
unsigned char SaveGIE = 0;
// Set EEPROM address
EEADR = addr%256;
// Set EEPROM data
EEDATA = value;
// Select Data
EECON1bits.EEPGD = 0;
// Select EEPROM
EECON1bits.CFGS = 0;
// Enable write
EECON1bits.WREN = 1;
// Save current global interrupt enable state
SaveGIE = INTCONbits.GIE;
// Disable interrupts
INTCONbits.GIE = 0;
// Write unlock sequence
EECON2 = 0x55;
EECON2 = 0xaa;
// Start write
EECON1bits.WR = 1;
// Restore previous interrupts enable state
INTCONbits.GIE = SaveGIE;
// Wait for write completion
while(EECON1bits.WR);
// Disable writes
EECON1bits.WREN = 0;
}
unsigned char EE_Read(unsigned char addr){
while(EECON1bits.RD || EECON1bits.WR); // check the WR&RD bit to see if a RD/WR is in progress
EEADR = addr; // Write the address to EEADR.
EECON1bits.CFGS = 0;
EECON1bits.EEPGD = 0;
EECON1bits.RD = 1; // Set the RD bit to trigger the eeprom read operation.
return(EEDATA);
}
答案 4 :(得分:0)
除内部闪存外,某些PIC18 micro还具有内部EEPROM。 18F87J11没有这个,所以你有两个选择:
1)写入闪存 - 这是存储程序的地方。确保您的应用程序的写入/读取周期数量正常。
2)使用外部i2c或spi内存进行配置设置
您正在使用的DataEEWrite来自微芯片的“eeprom仿真”库(在下面的评论中链接。有几件事需要注意:
答案 5 :(得分:0)
值255是EEPROM存储器的默认值。我想在更改代码后,您再次编程微控制器IC。因此,EEPROM存储器将被擦除并返回其默认值。如果使用MPLAB作为编译器,则可以转到“Programmer”选项卡&gt;设置..&gt;程序存储器&gt;程序选项,然后单击程序上的保留EEPROM。 希望它有效。
答案 6 :(得分:-2)
要保留电源循环的值,应使用SRAM存储器。请确认您是否首先提供SRAM内存。