嵌入式开发之 BootLoader:PEEK&POKE

来源:互联网 发布:unity3d gui texture 编辑:程序博客网 时间:2024/06/05 11:00

一 、 环境

  • Win10 64位
  • Keil
  • stm32f103c8

二、 STM32使用

具体请参见我的上一篇博客

配置stm32开发板以及初步使用


三、 连线图

这里写图片描述


四、 配置串口的输入输出

由于串口的传输是根据中断模式完成的,类似于上一个实验GPIO按钮的中断,于是我们需要实现串口的中断监听。

这里我犯了一个很低级的错误导致了开始时始终无法通过stm32的tx口把数据传输到电脑。
原因是stm32f1xx_hal_msp.c中没有对tx口进行input模式的初始化

GPIO_InitStruct.Mode = GPIO_MODE_INPUT;

接下来。
我们需要在main函数里写一个处理串口中断的函数

void USART1_IRQHandler(void){    //deal with interrupt    HAL_UART_IRQHandler(&huart1);}

在void MX_USART1_UART_Init(void) 的串口初始化函数里加入如下语句,开启串口的中断。

__HAL_UART_ENABLE(&huart1); HAL_NVIC_SetPriority(USART1_IRQn,0, 0);HAL_NVIC_EnableIRQ(USART1_IRQn);

然后加入下面这条语句,保证初始化时进入中断读取一次,将stm32板子上rx口的输入字符读入到指针c所指向的内存中,这里我们直接采用了一个数组c[2],定义为全局变量。

HAL_UART_Receive_IT(&huart1, (uint8_t*)c, 1);

下面是main函数中重要的全局变量

char c[1]; //串口接收到的字符的缓冲区int flag = 0; //条件变量,控制main函数中循环的阻塞char cmd[100]; //命令缓冲区char test[100]; //提示信息字符串(测试用的地址和长度)char *temp = cmd; // 指向cmd字符数组的指针int count=0; //命令的字符数

当中断被检测到时我们进入下面这个函数,也是定义在main函数中的。

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle){        if(temp<=cmd+CMD_LENGTH) //检测temp指针是否超过范围(temp指针开始指向cmd数组的基地址,cmd数组存放用户输入的指令)        {            count++; //记录用户输入串的长度            if(*c=='\r') // 如果是回车            {                *temp = '\0'; //将字符串结束符写入cmd字符数组                printString("\r\nYour command:"); //向串口输出该字符串                printString(cmd); //这里是为了验证输入是否写入了cmd数组                printString("\r\n");                flag = 1; //flag=0时,main函数里的while循环被阻塞                temp = cmd; //输入完一行后将temp指针重新指回cmd数组基址                count = 0; //将count置为0            }            else            {                *temp = *c; // 将该字符写入cmd数组                printChar(*temp); //串口输出给PC端该字符                temp++; //指针移向下一个地址            }        }        else            printString("Length of Command out of bound!\r\n");            HAL_UART_Receive_IT(UartHandle, (uint8_t*)c, 1); //每次处理结束后重新开始receive下一个字符到c缓冲区  }

五、 PEEK&POKE

  • SHELL
void exec(void){    char *word[100]={NULL};// 从命令中解析出来的单词数组    char s[100]; //    char *p = cmd;     int i = 0;    int addr=0; //PEEK和POKE的地址    int data=0; //对应地址的一个字的数据    word[i] = p;    while(*p!=0)//将命令解析到word数组中    {        if(*p==' ')        {            *p = '\0';            i++;            word[i] = p+1;        }        p++;    }    i=0;    while(word[i]!=0) //打印单词是否正确地被解析    {        printString(word[i]);        printString("\r\n");        i++;    }    if(i>3||i<=1) //如果单词数不是2或3 则命令错误        printString("Error number of args\r\n");    else    {        if(i==2) //应该是PEEK命令                if(strcmp(word[0],"peek")==0)                {                    sscanf(word[1],"%x",&addr); //将peek后的地址按%x格式输出到addr                    sprintf(s,"PEEK @%x --> %x\r\n",addr,*((int*)addr)); //按格式打印到字符串s                    printString(s);串口输出s                }                 else //如果不是输出指令类型错误                    printString("wrong type\r\n");        else if(i==3)//应该是POKE命令        {                if(strcmp(word[0],"poke")==0)                {                    sscanf(word[1],"%x",&addr);                    sscanf(word[2],"%x",&data);                    *((int*)addr) = data; 将地址对应的字写为data                    sprintf(s,"POKE @%x --> %x\r\n",addr,*((int*)addr));                    printString(s);                }                 else //如果不是POKE命令输出错误                    printString("wrong type\r\n");        }    }}
  • 结果
    这里写图片描述
0 1