[PIC®/AVR®/dsPIC®产品] 【CuriosityNano测评报告】+PIC16F15244 内部FLASH读写

[复制链接]
926|0
 楼主| qjp1988113 发表于 2021-2-22 14:18 | 显示全部楼层 |阅读模式
本帖最后由 qjp1988113 于 2021-2-22 14:24 编辑

今天我们来做下PIC16F15244 内部FLASH读写。这个几乎没有什么配置.打开MCC,选上MEMORY功能。

生成对应的代码,下面我们直接调用代码即可:
  1. /**
  2.   MEMORY Generated Driver File

  3.   @Company
  4.     Microchip Technology Inc.

  5.   [url=home.php?mod=space&uid=288409]@file[/url] Name
  6.     memory.c

  7.   @Summary
  8.     This is the generated driver implementation file for the MEMORY driver using PIC10 / PIC12 / PIC16 / PIC18 MCUs

  9.   @Description
  10.     This file provides implementations of driver APIs for MEMORY.
  11.     Generation Information :
  12.         Product Revision  :  PIC10 / PIC12 / PIC16 / PIC18 MCUs - 1.81.5
  13.         Device            :  PIC16F15244
  14.         Driver Version    :  2.01
  15.     The generated drivers are tested against the following:
  16.         Compiler          :  XC8 2.20 and above
  17.         MPLAB             :  MPLAB X 5.40
  18. */

  19. /*
  20.     (c) 2018 Microchip Technology Inc. and its subsidiaries.
  21.    
  22.     Subject to your compliance with these terms, you may use Microchip software and any
  23.     derivatives exclusively with Microchip products. It is your responsibility to comply with third party
  24.     license terms applicable to your use of third party software (including open source software) that
  25.     may accompany Microchip software.
  26.    
  27.     THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
  28.     EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY
  29.     IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS
  30.     FOR A PARTICULAR PURPOSE.
  31.    
  32.     IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE,
  33.     INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND
  34.     WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP
  35.     HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO
  36.     THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL
  37.     CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT
  38.     OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS
  39.     SOFTWARE.
  40. */

  41. /**
  42.   Section: Included Files
  43. */

  44. #include <xc.h>
  45. #include "memory.h"

  46. /**
  47.   Section: Flash Module APIs
  48. */

  49. uint16_t FLASH_ReadWord(uint16_t flashAddr)
  50. {
  51.     uint8_t GIEBitValue = INTCONbits.GIE;   // Save interrupt enable
  52.    
  53.     INTCONbits.GIE = 0;     // Disable interrupts
  54.     NVMADRL = (flashAddr & 0x00FF);
  55.     NVMADRH = ((flashAddr & 0xFF00) >> 8);

  56.     NVMCON1bits.NVMREGS = 0;    // Deselect Configuration space
  57.     NVMCON1bits.RD = 1;      // Initiate Read
  58.     NOP();
  59.     NOP();
  60.     INTCONbits.GIE = GIEBitValue;        // Restore interrupt enable

  61.     return ((uint16_t)((NVMDATH << 8) | NVMDATL));
  62. }

  63. void FLASH_WriteWord(uint16_t flashAddr, uint16_t *ramBuf, uint16_t word)
  64. {
  65.     uint16_t blockStartAddr = (uint16_t)(flashAddr & ((END_FLASH-1) ^ (ERASE_FLASH_BLOCKSIZE-1)));
  66.     uint8_t offset = (uint8_t)(flashAddr & (ERASE_FLASH_BLOCKSIZE-1));
  67.     uint8_t i;

  68.     // Entire row will be erased, read and save the existing data
  69.     for (i=0; i<ERASE_FLASH_BLOCKSIZE; i++)
  70.     {
  71.         ramBuf[i] = FLASH_ReadWord((blockStartAddr+i));
  72.     }

  73.     // Write at offset
  74.     ramBuf[offset] = word;

  75.     // Writes ramBuf to current block
  76.     FLASH_WriteBlock(blockStartAddr, ramBuf);
  77. }

  78. int8_t FLASH_WriteBlock(uint16_t writeAddr, uint16_t *flashWordArray)
  79. {
  80.     uint16_t    blockStartAddr  = (uint16_t )(writeAddr & ((END_FLASH-1) ^ (ERASE_FLASH_BLOCKSIZE-1)));
  81.     uint8_t     GIEBitValue = INTCONbits.GIE;   // Save interrupt enable
  82.     uint8_t i;

  83.    
  84.     // Flash write must start at the beginning of a row
  85.     if( writeAddr != blockStartAddr )
  86.     {
  87.         return -1;
  88.     }

  89.     INTCONbits.GIE = 0;         // Disable interrupts

  90.     // Block erase sequence
  91.     FLASH_EraseBlock(writeAddr);

  92.     // Block write sequence
  93.     NVMCON1bits.NVMREGS = 0;    // Deselect Configuration space
  94.     NVMCON1bits.WREN = 1;    // Enable wrties
  95.     NVMCON1bits.LWLO = 1;    // Only load write latches

  96.     for (i=0; i<WRITE_FLASH_BLOCKSIZE; i++)
  97.     {
  98.         // Load lower 8 bits of write address
  99.         NVMADRL = (writeAddr & 0xFF);
  100.         // Load upper 6 bits of write address
  101.         NVMADRH = ((writeAddr & 0xFF00) >> 8);

  102.         // Load data in current address
  103.         NVMDATL = flashWordArray[i];
  104.         NVMDATH = ((flashWordArray[i] & 0xFF00) >> 8);

  105.         if(i == (WRITE_FLASH_BLOCKSIZE-1))
  106.         {
  107.             // Start Flash program memory write
  108.             NVMCON1bits.LWLO = 0;
  109.         }

  110.         NVMCON2 = 0x55;
  111.         NVMCON2 = 0xAA;
  112.         NVMCON1bits.WR = 1;
  113.         NOP();
  114.         NOP();

  115.         writeAddr++;
  116.     }

  117.     NVMCON1bits.WREN = 0;       // Disable writes
  118.     INTCONbits.GIE = GIEBitValue;   // Restore interrupt enable

  119.     return 0;
  120. }

  121. void FLASH_EraseBlock(uint16_t startAddr)
  122. {
  123.     uint8_t GIEBitValue = INTCONbits.GIE;   // Save interrupt enable
  124.    

  125.     INTCONbits.GIE = 0; // Disable interrupts
  126.     // Load lower 8 bits of erase address boundary
  127.     NVMADRL = (startAddr & 0xFF);
  128.     // Load upper 6 bits of erase address boundary
  129.     NVMADRH = ((startAddr & 0xFF00) >> 8);

  130.     // Block erase sequence
  131.     NVMCON1bits.NVMREGS = 0;    // Deselect Configuration space
  132.     NVMCON1bits.FREE = 1;    // Specify an erase operation
  133.     NVMCON1bits.WREN = 1;    // Allows erase cycles

  134.     // Start of required sequence to initiate erase
  135.     NVMCON2 = 0x55;
  136.     NVMCON2 = 0xAA;
  137.     NVMCON1bits.WR = 1;      // Set WR bit to begin erase
  138.     NOP();
  139.     NOP();

  140.     NVMCON1bits.WREN = 0;       // Disable writes
  141.     INTCONbits.GIE = GIEBitValue;        // Restore interrupt enable
  142. }

  143. /**
  144.   Section: Data EEPROM Module APIs
  145. */

  146. void DATAEE_WriteByte(uint16_t bAdd, uint8_t bData)
  147. {
  148.     uint8_t GIEBitValue = INTCONbits.GIE;

  149.     NVMADRH = ((bAdd >> 8) & 0xFF);
  150.     NVMADRL = (bAdd & 0xFF);
  151.     NVMDATL = bData;   
  152.     NVMCON1bits.NVMREGS = 1;
  153.     NVMCON1bits.WREN = 1;
  154.     INTCONbits.GIE = 0;     // Disable interrupts
  155.     NVMCON2 = 0x55;
  156.     NVMCON2 = 0xAA;
  157.     NVMCON1bits.WR = 1;
  158.     // Wait for write to complete
  159.     while (NVMCON1bits.WR)
  160.     {
  161.     }

  162.     NVMCON1bits.WREN = 0;
  163.     INTCONbits.GIE = GIEBitValue;   // restore interrupt enable
  164. }

  165. uint8_t DATAEE_ReadByte(uint16_t bAdd)
  166. {
  167.     NVMADRH = ((bAdd >> 8) & 0xFF);
  168.     NVMADRL = (bAdd & 0xFF);
  169.     NVMCON1bits.NVMREGS = 1;   
  170.     NVMCON1bits.RD = 1;
  171.     NOP();  // NOPs may be required for latency at high frequencies
  172.     NOP();

  173.     return (NVMDATL);
  174. }


  175. /**
  176. End of File
  177. */



这里要说明的是,我们用来作为存储一些设定数字的FLASH地址一定要大于程序本身生成的代码,最好用最后面几个地址。
同时要计时个数,不能超出范围,不然会死机。
我们的MCU对应的FLASH地址范围 0X000~0XFFF

FLASH具有划分及堆栈模式:

可以在IDE左下侧,查看当前使用情况。

我们这里向首地址为0XF00的位置写入"Hello,world!",然后再把它读出来,看是否正确!
main.c定义变量:
  1. #define FLASH_ROW_ADDRESS     0x0F00

  2. uint16_t wrBlockData[12] ={'H', 'e', 'l', 'l', 'o', ',', 'w', 'o', 'r','l','d','!'};
  3. uint16_t receData[12]={0};
添加到main里面:
  1. for(i=0;i<12;i++)
  2.     {
  3.         receData[i]=0;
  4.     }
  5.     // write to Flash memory block
  6.     FLASH_WriteBlock((uint16_t)FLASH_ROW_ADDRESS, (uint16_t*)wrBlockData);
  7.     __delay_ms(500);
  8.     for(i=0;i<12;i++)
  9.     {
  10.         receData[i]=FLASH_ReadWord((uint16_t)FLASH_ROW_ADDRESS+i);
  11.         __delay_ms(2);
  12.     }
  13.     __delay_ms(500);   
  14.     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],
  15.             receData[4],receData[5],receData[6],receData[7],receData[8],receData[9],receData[10],receData[11]);
就不做数值转字符串的代码了,编译下载,直接显示:

使用起来还行,但奈何本身空间就很小,当程序代码多时,慎用,会出现莫名其妙的问题。
之前我在循环里面加了读取ADC,并串口输出,然后大数据的转换处理就出现问题了,出现一个不稳定的值~






本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

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

本版积分规则

111

主题

627

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部