打开主菜单

谷雨文档中心 β

更改

NRF52832DK基础实验

添加5,753字节2019年7月18日 (四) 15:07
flash readwrite
==== 代码分析 ====
开发者打开谷雨物联提供的peripheral_ghostyu文件夹中11_flash_readwrite_example工程(IAR工程)。
 
在IAR的Workspace中点开Application,双击main.c文件,打开main.c。<syntaxhighlight lang="c" line="1">
int main(void)
{
clock_config(); //初始化时钟
LED_Init(); //LED 初始化
UART_Init(APP_UartEvtHandle); //初始化串口
Flash_info_init();
bsp_board_lcd_init(); //初始化LCD使用的外设,SPI,GPIO
GUI_Init(); //初始化LCD
GUI_DispStringAt("Flash Test\r\n",0,0); //显示字符
GUI_SetColor(GUI_BLUE);
//串口打印字符串
printf("Flash Test\r\n");
Flash_info_out();
printf(CLI_PROMPT_STRINGS);
for(;;)
{
APP_UartPoll();
}
}
</syntaxhighlight>main函数中,对用到的外设和软件模块进行初始化。其中flash_info_out函数获取芯片的flash信息,包括页数,页大小,flash大小,RAM大小等。<syntaxhighlight lang="c" line="1">
static void Flash_info_out(void)
{
uint32_t codesize = NRF_FICR->CODESIZE;
uint32_t codepagesize = NRF_FICR->CODEPAGESIZE;
uint32_t ramsize = NRF_FICR->INFO.RAM;
uint32_t romsize = NRF_FICR->INFO.FLASH;
uint32_t deviceid0 = NRF_FICR->DEVICEID[0];
uint32_t deviceid1 = NRF_FICR->DEVICEID[1];
//打印芯片信息
printf("FLASH INFO:\r\npage num :%d\r\npage size:%d\r\nram size:%dk\r\nflash size:%dk\r\ndevice id0:0x%08X\r\ndevice id1:0x%08X\r\n",
codesize,
codepagesize,
ramsize,
romsize,
deviceid0,
deviceid1
);
GUI_Disprintf("\r\nPNum:%d\r\n",flash_info.page_num);
GUI_Disprintf("PSize:%d\r\n",flash_info.page_size);
GUI_Disprintf("Addr:0x%X\r\n",flash_info.opt_addr);
}
</syntaxhighlight>CLI_PROMPT_STRINGS是命令行提示字符,用于提示命令输入。<syntaxhighlight lang="c">
#define CLI_PROMPT_STRINGS "\r\nNRF_Flash#:"
</syntaxhighlight>所有串口命令处理都在APP_UartPoll函数中。有关串口低层收发处理,此例程中不作说明,开发者可以查看《08_UART收发实验》例程。<syntaxhighlight lang="c" line="1">
static int APP_UartPoll(void)
{
uint8_t len = 0;
switch(uart_evt.evt_type)
{
case UART_EVT_RX_TIMEOUT:
case UART_EVT_RX_OVERFLOW:
//检查是否将会溢出
if((cmd_buf.len + uart_evt.status) > (USER_CMD_MAX_LEN -1))
{
len = UART_BUF_SIZE - 1 - cmd_buf.len;
}
else
{
len = uart_evt.status;
}
//回显
len = UART_Read(cmd_buf.Buf + cmd_buf.len,len);
UART_Write(cmd_buf.Buf + cmd_buf.len,len);
cmd_buf.len += len;
cmd_buf.Buf[cmd_buf.len] = 0;
//进行命令解析
if((cmd_buf.len >= USER_CMD_MAX_LEN) || (strchr((char const*)cmd_buf.Buf,'\r')))
{
printf("\r\n");
if(CLI_Process(cmd_buf.Buf))
{
printf("error\r\n");
}
cmd_buf.len = 0;
printf(CLI_PROMPT_STRINGS);
}
uart_evt.evt_type = UART_EVT_NONE;
break;
default :
break;
}
return len;
}
</syntaxhighlight>串口在收到控制台发来数据后,通过UART_EVT_RX_TIMEOUT事件回调到上层,并将收到数据回显到控制台,以显示开发者输入字符。接下来就是对命令数据进行结束识别。结束条件分为两种:一是最大长度为USER_CMD_MAX_LEN;二是回车换行符。
 
最终对命令进行解析的是CLI_Process函数。利用strtok库函数对命令数据进行分割,分割字符为空格。所以开发者在命令输入时,要以空格作为分隔。最后将分割的数据与个数传入CMD_ExcuteHandle函数。<syntaxhighlight lang="c" line="1">
CMD_CODE_T CLI_Process(uint8_t* buf)
{
char *pTmp = NULL;
char* argv[10];
size_t count = 0;
if(buf == NULL)
{
//数据内容为空,直接返回
return CMD_BAD_BUF;
}
pTmp = (char*)strchr((char const*)buf,'\r');
if(pTmp)
{
*pTmp = '\0';
}
pTmp = (char*)buf;
//提取指令返回的参数,此时buf已经遭到破坏
while((argv[count] = strtok(pTmp," ")) != NULL)
{
count++;
pTmp = NULL;
if(count >=10)
{
break;
}
}
return CMD_ExcuteHandle(count,argv);
}
</syntaxhighlight>CMD_ExcuteHandle函数会根据输入参数查找命令库。如果查找到将执行命令,否则返回CMD_NOT_FIND。
 
与命令相关的数据结构如下。<syntaxhighlight lang="c">
typedef void (*cmd_handler)(size_t argc, char **argv);
 
typedef struct
{
const char* cmd; //cmd
cmd_handler handler; //handler
}cmd_item_t;
</syntaxhighlight>其中cmd是命令名字,handler是命令执行函数。所以开发者,想要实现命令,只要向cmd_item中添加命令名字与处理函数即可,如下。<syntaxhighlight lang="c" line="1">
//增加命令条目
const cmd_item_t cmd_item[] =
{
{STRINGIFY(read),Flash_read_cmd},
{STRINGIFY(write),Flash_write_cmd},
{STRINGIFY(erase),Flash_erase_cmd},
{NULL,NULL}
};
</syntaxhighlight>
==== 实验现象 ====
硬件准备:
# Jlink-Lite仿真器或J-Link仿真器
# NRF52832DK评估板
# TFT-LCD-144或TFT-LCD-130显示屏
编译工程,点击IAR IDE工具栏中绿色三角仿真按钮,IAR便会将程序下载到nRF52832中,点击全速运行即可。此时NRF52832DK上的LCD显示屏会显地当前操作Flash信息,包括页号,此页大小及所在地址。而此时控制台也会收到相应的信息。
[[文件:Flash uart reset.png|居中|缩略图|547x547像素]]
开发者可以根据命令条目,输入命令进行简单调试。read -> write -> read。
[[文件:Flash readwrite.png|居中|缩略图|720x720像素]]
119
个编辑