- /**
- MEMORY Generated Driver File
- @Company
- Microchip Technology Inc.
- [url=home.php?mod=space&uid=288409]@file[/url] Name
- memory.c
- @Summary
- This is the generated driver implementation file for the MEMORY driver using PIC10 / PIC12 / PIC16 / PIC18 MCUs
- @Description
- This file provides implementations of driver APIs for MEMORY.
- Generation Information :
- Product Revision : PIC10 / PIC12 / PIC16 / PIC18 MCUs - 1.81.5
- Device : PIC16F15244
- Driver Version : 2.01
- The generated drivers are tested against the following:
- Compiler : XC8 2.20 and above
- MPLAB : MPLAB X 5.40
- */
- /*
- (c) 2018 Microchip Technology Inc. and its subsidiaries.
-
- Subject to your compliance with these terms, you may use Microchip software and any
- derivatives exclusively with Microchip products. It is your responsibility to comply with third party
- license terms applicable to your use of third party software (including open source software) that
- may accompany Microchip software.
-
- THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
- EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY
- IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS
- FOR A PARTICULAR PURPOSE.
-
- IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE,
- INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND
- WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP
- HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO
- THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL
- CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT
- OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS
- SOFTWARE.
- */
- /**
- Section: Included Files
- */
- #include <xc.h>
- #include "memory.h"
- /**
- Section: Flash Module APIs
- */
- uint16_t FLASH_ReadWord(uint16_t flashAddr)
- {
- uint8_t GIEBitValue = INTCONbits.GIE; // Save interrupt enable
-
- INTCONbits.GIE = 0; // Disable interrupts
- NVMADRL = (flashAddr & 0x00FF);
- NVMADRH = ((flashAddr & 0xFF00) >> 8);
- NVMCON1bits.NVMREGS = 0; // Deselect Configuration space
- NVMCON1bits.RD = 1; // Initiate Read
- NOP();
- NOP();
- INTCONbits.GIE = GIEBitValue; // Restore interrupt enable
- return ((uint16_t)((NVMDATH << 8) | NVMDATL));
- }
- void FLASH_WriteWord(uint16_t flashAddr, uint16_t *ramBuf, uint16_t word)
- {
- uint16_t blockStartAddr = (uint16_t)(flashAddr & ((END_FLASH-1) ^ (ERASE_FLASH_BLOCKSIZE-1)));
- uint8_t offset = (uint8_t)(flashAddr & (ERASE_FLASH_BLOCKSIZE-1));
- uint8_t i;
- // Entire row will be erased, read and save the existing data
- for (i=0; i<ERASE_FLASH_BLOCKSIZE; i++)
- {
- ramBuf[i] = FLASH_ReadWord((blockStartAddr+i));
- }
- // Write at offset
- ramBuf[offset] = word;
- // Writes ramBuf to current block
- FLASH_WriteBlock(blockStartAddr, ramBuf);
- }
- int8_t FLASH_WriteBlock(uint16_t writeAddr, uint16_t *flashWordArray)
- {
- uint16_t blockStartAddr = (uint16_t )(writeAddr & ((END_FLASH-1) ^ (ERASE_FLASH_BLOCKSIZE-1)));
- uint8_t GIEBitValue = INTCONbits.GIE; // Save interrupt enable
- uint8_t i;
-
- // Flash write must start at the beginning of a row
- if( writeAddr != blockStartAddr )
- {
- return -1;
- }
- INTCONbits.GIE = 0; // Disable interrupts
- // Block erase sequence
- FLASH_EraseBlock(writeAddr);
- // Block write sequence
- NVMCON1bits.NVMREGS = 0; // Deselect Configuration space
- NVMCON1bits.WREN = 1; // Enable wrties
- NVMCON1bits.LWLO = 1; // Only load write latches
- for (i=0; i<WRITE_FLASH_BLOCKSIZE; i++)
- {
- // Load lower 8 bits of write address
- NVMADRL = (writeAddr & 0xFF);
- // Load upper 6 bits of write address
- NVMADRH = ((writeAddr & 0xFF00) >> 8);
- // Load data in current address
- NVMDATL = flashWordArray[i];
- NVMDATH = ((flashWordArray[i] & 0xFF00) >> 8);
- if(i == (WRITE_FLASH_BLOCKSIZE-1))
- {
- // Start Flash program memory write
- NVMCON1bits.LWLO = 0;
- }
- NVMCON2 = 0x55;
- NVMCON2 = 0xAA;
- NVMCON1bits.WR = 1;
- NOP();
- NOP();
- writeAddr++;
- }
- NVMCON1bits.WREN = 0; // Disable writes
- INTCONbits.GIE = GIEBitValue; // Restore interrupt enable
- return 0;
- }
- void FLASH_EraseBlock(uint16_t startAddr)
- {
- uint8_t GIEBitValue = INTCONbits.GIE; // Save interrupt enable
-
- INTCONbits.GIE = 0; // Disable interrupts
- // Load lower 8 bits of erase address boundary
- NVMADRL = (startAddr & 0xFF);
- // Load upper 6 bits of erase address boundary
- NVMADRH = ((startAddr & 0xFF00) >> 8);
- // Block erase sequence
- NVMCON1bits.NVMREGS = 0; // Deselect Configuration space
- NVMCON1bits.FREE = 1; // Specify an erase operation
- NVMCON1bits.WREN = 1; // Allows erase cycles
- // Start of required sequence to initiate erase
- NVMCON2 = 0x55;
- NVMCON2 = 0xAA;
- NVMCON1bits.WR = 1; // Set WR bit to begin erase
- NOP();
- NOP();
- NVMCON1bits.WREN = 0; // Disable writes
- INTCONbits.GIE = GIEBitValue; // Restore interrupt enable
- }
- /**
- Section: Data EEPROM Module APIs
- */
- void DATAEE_WriteByte(uint16_t bAdd, uint8_t bData)
- {
- uint8_t GIEBitValue = INTCONbits.GIE;
- NVMADRH = ((bAdd >> 8) & 0xFF);
- NVMADRL = (bAdd & 0xFF);
- NVMDATL = bData;
- NVMCON1bits.NVMREGS = 1;
- NVMCON1bits.WREN = 1;
- INTCONbits.GIE = 0; // Disable interrupts
- NVMCON2 = 0x55;
- NVMCON2 = 0xAA;
- NVMCON1bits.WR = 1;
- // Wait for write to complete
- while (NVMCON1bits.WR)
- {
- }
- NVMCON1bits.WREN = 0;
- INTCONbits.GIE = GIEBitValue; // restore interrupt enable
- }
- uint8_t DATAEE_ReadByte(uint16_t bAdd)
- {
- NVMADRH = ((bAdd >> 8) & 0xFF);
- NVMADRL = (bAdd & 0xFF);
- NVMCON1bits.NVMREGS = 1;
- NVMCON1bits.RD = 1;
- NOP(); // NOPs may be required for latency at high frequencies
- NOP();
- return (NVMDATL);
- }
- /**
- End of File
- */
这里要说明的是,我们用来作为存储一些设定数字的FLASH地址一定要大于程序本身生成的代码,最好用最后面几个地址。
同时要计时个数,不能超出范围,不然会死机。
我们的MCU对应的FLASH地址范围 0X000~0XFFF
FLASH具有划分及堆栈模式:
可以在IDE左下侧,查看当前使用情况。
我们这里向首地址为0XF00的位置写入"Hello,world!",然后再把它读出来,看是否正确!
main.c定义变量:
- #define FLASH_ROW_ADDRESS 0x0F00
- uint16_t wrBlockData[12] ={'H', 'e', 'l', 'l', 'o', ',', 'w', 'o', 'r','l','d','!'};
- uint16_t receData[12]={0};
添加到main里面:
- for(i=0;i<12;i++)
- {
- receData[i]=0;
- }
- // write to Flash memory block
- FLASH_WriteBlock((uint16_t)FLASH_ROW_ADDRESS, (uint16_t*)wrBlockData);
- __delay_ms(500);
- for(i=0;i<12;i++)
- {
- receData[i]=FLASH_ReadWord((uint16_t)FLASH_ROW_ADDRESS+i);
- __delay_ms(2);
- }
- __delay_ms(500);
- printf("\r\n the readata is: %c%c%c%c%c%c%c%c%c%c%c%c \r\n",receData[0],receData[1],receData[2],receData[3],
- receData[4],receData[5],receData[6],receData[7],receData[8],receData[9],receData[10],receData[11]);
就不做数值转字符串的代码了,编译下载,直接显示:
使用起来还行,但奈何本身空间就很小,当程序代码多时,慎用,会出现莫名其妙的问题。
之前我在循环里面加了读取ADC,并串口输出,然后大数据的转换处理就出现问题了,出现一个不稳定的值~