嵌入式开发之 BootLoader:PEEK&POKE

一 、 环境

  • 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
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值