1.前言
MSP430F5438的片内FLASH可以当做EEPROM使用,该部分FLASH称为INFO FLASH,总共有4块每块128Byte。虽然INFO FLASH容量比较少,但是多数情况还是够用的。
【2014年1月回顾】 存在问题需要立刻改进
2.代码实现
[cpp] view plaincopy
- // 时钟默认情况
- // FLL时钟 FLL选择 XT1
- // 辅助时钟 ACLK选择 XT1 32768Hz
- // 主系统时钟 MCLK选择 DCOCLKDIV 8000000Hz
- // 子系统时钟 SMCLK选择 DCOCLKDIV 8000000Hz
- // UART时钟选择 ACLK
- // 低频波特率产生 9600-8-N-1
- #include <msp430.h>
- #include <stdio.h>
- #include <stdint.h>
- void clock_config(void);
- void select_xt1(void);
- void dco_config(void);
- void uart_config(void);
- void flash_writebuf(uint8_t *flash_ptr,uint8_t *buffer,uint8_t len);
- void flash_readbuf(uint8_t *flash_ptr,uint8_t *buffer,uint8_t len);
- int main(void)
- {
- clock_config(); // 初始化时钟
- uart_config(); // 初始化UART
- _EINT();
- // 打印时间和提示信息
- printf("Date: %s %s\r\n", __DATE__,__TIME__);
- printf("Flash Test!\r\n");
- #if 0
- uint8_t test_buffer[8] = {1,2,3,4,5,6,7,8};
- flash_writebuf((uint8_t*)0x1800, test_buffer,8);
- #endif
- uint8_t old_flash[8] = {0,};
- uint8_t new_flash[8] = {0,};
- // 从info flash 0x1800处连续读出8个字节
- flash_readbuf((uint8_t*)0x1800,old_flash,8);
- for( uint8_t i = 0 ; i < 8 ; i++ )
- {
- printf("ADDR:0X%4X,%-2X\r\n",0x1800+i,old_flash);
- new_flash = old_flash + 1;
- }
- // 累加之后再次写入
- flash_writebuf((uint8_t*)0x1800,new_flash,8);
- while(1)
- {
- }
- }
- void flash_writebuf(uint8_t *flash_ptr,uint8_t *buffer,uint8_t len)
- {
- __disable_interrupt(); // 禁止中断
- FCTL3 = FWKEY; // 设置写密钥并解锁
- FCTL1 = FWKEY+ERASE; // 段擦除
- *(unsigned int *)flash_ptr = 0; // ??
- FCTL1 = FWKEY+WRT; // 字节写入
- for ( uint8_t i = 0; i < len; i++)
- {
- *flash_ptr++ = *buffer++;
- }
- FCTL1 = FWKEY; // 设置写密钥
- FCTL3 = FWKEY+LOCK; // 重新锁住
- __enable_interrupt(); // 恢复中断
- }
- void flash_readbuf(uint8_t *flash_ptr,uint8_t *buffer,uint8_t len)
- {
- __disable_interrupt();
- for( uint8_t i = 0 ; i < len ; i++ )
- {
- *buffer++ = *flash_ptr++;
- }
- __enable_interrupt();
- }
- void clock_config(void)
- {
- WDTCTL = WDTPW + WDTHOLD; // 停止看门狗
- select_xt1(); // 选择XT1
- dco_config(); // ACLK = XT1 = 32.768K
- // MCLK = SMCLK = 8000K
- }
- void select_xt1(void)
- {
- // 启动XT1
- P7SEL |= 0x03; // P7.0 P7.1 外设功能
- UCSCTL6 &= ~(XT1OFF); // XT1打开
- UCSCTL6 |= XCAP_3; // 内部电容
- do
- {
- UCSCTL7 &= ~XT1LFOFFG; // 清楚XT1错误标记
- }while (UCSCTL7&XT1LFOFFG); // 检测XT1错误标记
- }
- void dco_config(void)
- {
- __bis_SR_register(SCG0); // 禁止FLL功能
- UCSCTL0 = 0x0000; // Set lowest possible DCOx, MODx
- UCSCTL1 = DCORSEL_5; // DCO最大频率为16MHz
- UCSCTL2 = FLLD_1 + 243; // 设置DCO频率为8MHz
- // MCLK = SMCLK= Fdcoclkdiv = (N+1)X(Ffllrefclk/n)
- // N为唯一需要计算的值
- // Ffllrefclk FLL参考时钟,默认为XT1
- // n取默认值,此时为1
- // (243 + 1) * 32768 = 8MHz
- __bic_SR_register(SCG0); // 使能FLL功能
- // 必要延时
- __delay_cycles(250000);
- // 清楚错误标志位
- do
- {
- UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + XT1HFOFFG + DCOFFG);
- // 清除所有振荡器错误标志位
- SFRIFG1 &= ~OFIFG; // 清除振荡器错误
- }while (SFRIFG1&OFIFG); // 等待清楚完成
- }
- void uart_config(void)
- {
- P3SEL = 0x30; // 选择P3.4和P3.5的复用功能
- UCA0CTL1 |= UCSWRST; // 软件复位
- UCA0CTL1 |= UCSSEL_1; // 选择ACLK时钟
- UCA0BR0 = 3; // 查表获得
- UCA0BR1 = 0; // UCA0BRX和UCA0MCTL数值
- UCA0MCTL |= UCBRS_3 + UCBRF_0; //
- UCA0CTL1 &= ~UCSWRST; //
- UCA0IE |= UCRXIE; // 使能接收中断
- }
- int putchar(int ch)
- {
- UCA0TXBUF = ch;
- while(!(UCA0IFG & UCTXIFG));
- return ch;
- }
|