如何使用PIC18写入和读取内存?
我想将一个数字存储到PIC18,然后保留它,即使断电或设备复位。我认为我的编写代码部分看起来不错,只是在重置单元后,它的读取部分看起来很奇怪 我使用的是从Microchip获得的以下代码 代码:如何使用PIC18写入和读取内存?,c,microcontroller,microchip,mplab,pic18,C,Microcontroller,Microchip,Mplab,Pic18,我想将一个数字存储到PIC18,然后保留它,即使断电或设备复位。我认为我的编写代码部分看起来不错,只是在重置单元后,它的读取部分看起来很奇怪 我使用的是从Microchip获得的以下代码 代码: unsigned int value; unsigned int DEEdata = 1; unsigned int DEEaddr = 0x04; DataEEInit(); dataEEFlags.val = 0; DataEEWrite(DEEdata,DEEaddr); value = D
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
为什么会这样?我假设可能没有保存值或读取部分不正确。谢谢大家! 要在电源循环时保留值,应使用SRAM内存。请先确认您是否有可用的SRAM内存。您正在使用的设备除了通常用于存储代码的闪存之外,没有内部非易失性内存 我可以看到您有两个选择:
void my_assembler_function(void)
{
// Inline assembler code, actioned via C.
asm("MOV x y");
asm("MOV y z");
}
或者,许多微处理器的C编译器允许您使用C函数调用外部.s
文件,从而避免了内联调用
我想你可以按照我找到的例子来实际实现你想要的功能。一些PIC18微型机除了内部闪存之外还有一个内部EEPROM。18F87J11没有此功能,因此您有2个选项: 1) 写入闪存-这是存储程序的地方。确保应用程序的写入/读取周期数正常 2) 使用外部i2c或spi内存进行配置设置 您使用的DataEEWrite来自microchip的“eeprom仿真”库(链接在下面的评论中)。有几件事需要注意:
- 重新编程闪存时请小心!您可能会覆盖您的设置
- 请记住,它不是真正的eeprom!写入周期是有限的,您必须擦除大部分内存-您不能擦除一个字节
3.PIC18数据仿真库。255的值是EEPROM内存的默认值。我认为在更改代码后,您可以重新编程微控制器IC。因此,您的EEPROM内存将被擦除并返回其默认值。如果您使用MPLAB作为编译器,您可以转到“程序员”选项卡>设置>程序内存>程序选项和click on保存EEPROM on程序。
希望它能工作。两个功能:使用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
}
}
/******************************************************
*功能:写入块
*输入:uint16\t目标闪存中的位置
*全局:uint8\u t缓冲区[64]-源数据的位置
*输出:无
*描述:写入64字节的内容
*数据缓冲区用于编程闪存空间。仅64字节
*可以一次完成。写作的过程
*闪存是:擦除->写入。
******************************************************/
静态无效写入块(uint16地址)
{
int r,c;
//首先擦除闪存块。一次擦除64字节块。
加载待测PTR(地址);
EECON1bits.EEPGD=1;//指向闪存程序存储器
EECON1bits.CFGS=0;//访问闪存
EECON1bits.WREN=1;//启用对内存的写入
EECON1bits.FREE=1;//启用擦除操作
EECON2=0x55;
EECON2=0xAA;
EECON1bits.WR=1;//清除闪光灯
asm(“NOP”);//暂停
//将缓冲区写入内部缓冲区。此进程一次写入8字节
//所以我们需要循环8次(8*8=64)
对于(r=0;r<8;r++)
{
加载(addr+(r*8));
对于(c=0;c
验证写入数据(演示闪存读取)
/******************
/******************************************************
* 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;
}
/* 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);
}