• Basic脚本解释器移植到STM32


    本文来自http://blog.csdn.net/hellogv/ 。引用必须注明出处!

       

    上次讲了LUA移植到STM32。这次讲讲Basic脚本解释器移植到STM32。

    在STM32上跑Basic脚本,相同能够跟穿戴设备结合。也能够作为刚開始学习的人学习MCU的入门工具,当然前提是有人做好Basic的STM32交互实现。这里使用的是uBasic开源脚本解释器(http://dunkels.com/adam/ubasic/),只是uBasic不支持完整的Basic算法,所以用起来略费心,假设有好的Basic开源脚本解释器。ANSI-C实现的,欢迎推荐。。

    本文实现的功能是输入下面basic脚本:

    10 v=1
    20 for p = 4 to 7
    40 write "gpioa",p,v
    50 next p
    60 if v=0 then goto 10
    70 if v=1 then v=0
    80 goto 20
    run
    实现的功能是同一时候把4个LED灯同一时候开后再同一时候关,通过自己定义的命令 write来实现,p是IO脚。v是IO的数值。
    write "gpioa",p,v

    例如以下图:

    本文代码能够到这里下载http://download.csdn.net/detail/hellogv/7391265

    main.c的源代码例如以下,通过USART1来发送Basic脚本到STM32,另外还要通过readline()来做些预处理,比如收到“run”这个字符串就表示脚本结束開始执行:

    #include "stm32f10x_lib.h"
    #include <assert.h>
    #include "stdio.h"
    #include <stdlib.h>
    #include <string.h>
    #include "ubasic.h"
    
    /*******************************************************************************
     * 函数名  : RCC_Configuration
     * 函数描写叙述  : 设置系统各部分时钟
     *******************************************************************************/
    
    void RCC_Configuration(void) {
      /* 定义枚举类型变量 HSEStartUpStatus */
      ErrorStatus HSEStartUpStatus;
    
      /* 复位系统时钟设置*/
      RCC_DeInit();
      /* 开启HSE*/
      RCC_HSEConfig(RCC_HSE_ON );
      /* 等待HSE起振并稳定*/
      HSEStartUpStatus = RCC_WaitForHSEStartUp();
      /* 推断HSE起是否振成功,是则进入if()内部 */
      if (HSEStartUpStatus == SUCCESS) {
        /* 选择HCLK(AHB)时钟源为SYSCLK 1分频 */
        RCC_HCLKConfig(RCC_SYSCLK_Div1 );
        /* 选择PCLK2时钟源为 HCLK(AHB) 1分频 */
        RCC_PCLK2Config(RCC_HCLK_Div1 );
        /* 选择PCLK1时钟源为 HCLK(AHB) 2分频 */
        RCC_PCLK1Config(RCC_HCLK_Div2 );
        /* 设置FLASH延时周期数为2 */
        FLASH_SetLatency(FLASH_Latency_2 );
        /* 使能FLASH预取缓存 */
        FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable );
        /* 选择锁相环(PLL)时钟源为HSE 1分频。倍频数为9。则PLL输出频率为 8MHz * 9 = 72MHz */
        RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9 );
        /* 使能PLL */
        RCC_PLLCmd(ENABLE);
        /* 等待PLL输出稳定 */
        while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY ) == RESET)
          ;
        /* 选择SYSCLK时钟源为PLL */
        RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK );
        /* 等待PLL成为SYSCLK时钟源 */
        while (RCC_GetSYSCLKSource() != 0x08)
          ;
      }
    
      /* 开启USART1和GPIOA时钟 */
      RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA,
          ENABLE);
    }
    
    /*******************************************************************************
     * 函数名      : GPIO_Configuration
     * 函数描写叙述      : 设置各GPIOport功能
     *******************************************************************************/
    
    void GPIO_Configuration(void) {
      /* 定义GPIO初始化结构体 GPIO_InitStructure */
      GPIO_InitTypeDef GPIO_InitStructure;
    
      /* 设置USART1的Tx脚(PA.9)为第二功能推挽输出功能 */
      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
      GPIO_Init(GPIOA, &GPIO_InitStructure);
    
      /* 设置USART1的Rx脚(PA.10)为浮空输入脚 */
      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
      GPIO_Init(GPIOA, &GPIO_InitStructure);
    }
    
    /*******************************************************************************
     * 函数名      : USART_Configuration
     * 函数描写叙述      : 设置USART1
     *******************************************************************************/
    
    void USART_Configuration(void) {
      /* 定义USART初始化结构体 USART_InitStructure */
      USART_InitTypeDef USART_InitStructure;
      /* 定义USART初始化结构体 USART_ClockInitStructure */
      USART_ClockInitTypeDef USART_ClockInitStructure;
    
      /*  波特率为115200bps;
       *  8位数据长度;
       *  1个停止位。无校验;
       *  禁用硬件流控制;
       *  禁止USART时钟;
       *  时钟极性低;
       *  在第2个边沿捕获数据
       *  最后一位数据的时钟脉冲不从 SCLK 输出;
       */
    
      USART_ClockInitStructure.USART_Clock = USART_Clock_Disable;
      USART_ClockInitStructure.USART_CPOL = USART_CPOL_Low;
      USART_ClockInitStructure.USART_CPHA = USART_CPHA_2Edge;
      USART_ClockInitStructure.USART_LastBit = USART_LastBit_Disable;
      USART_ClockInit(USART1, &USART_ClockInitStructure);
    
      USART_InitStructure.USART_BaudRate = 9600;
      USART_InitStructure.USART_WordLength = USART_WordLength_8b;
      USART_InitStructure.USART_StopBits = USART_StopBits_1;
      USART_InitStructure.USART_Parity = USART_Parity_No ;
      USART_InitStructure.USART_HardwareFlowControl =USART_HardwareFlowControl_None;
      USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
      USART_Init(USART1, &USART_InitStructure);
    
      /* 使能USART1 */
      USART_Cmd(USART1, ENABLE);
    }
    
    int fputc(int ch, FILE *f) {
      USART_SendData(USART1, (u8) ch);
      while (USART_GetFlagStatus(USART1, USART_FLAG_TC ) == RESET);
      return ch;
    }
    
    int getKey(void) {
      while (!(USART1 ->SR & USART_FLAG_RXNE ));
      return ((int) (USART1 ->DR & 0x1FF));
    }
    
    /*******************************************************************************
     * 函数名      : readLine
     * 函数描写叙述      : 从串口读取Basic代码
     *******************************************************************************/
    bool readLines(char *s) {
      bool isString = FALSE; //推断是否字符串
      char ch;
      char *p = s;
      
      if(*p!='')
        return FALSE;
      
      while (1) {
        ch = getKey();
        if (ch == '"') { //检測到字符串
          isString = !isString;
        }
    
        if (ch == '
    ') //屏蔽'
    '这个字符
          continue;
        else {
          if (isString) //不改变代码中字符串的大写和小写
            *p++ = ch;
          else //关键字都转为小写
            *p++ = tolower(ch);
        }
        
        if (*(p-3) == 'r'
              &&*(p-2)=='u'
              &&*(p-1)=='n'){ //run表示程序结束
          *(p-3) = '';
          break;
        }
      }
      return TRUE;
    }
    
    #define _MAX_LINE_LENGTH 256
    int main(void) {
      /* 设置系统时钟 */
      RCC_Configuration();
      /* 设置GPIOport */
      GPIO_Configuration();
      /* 设置USART */
      USART_Configuration();
    
      char line[_MAX_LINE_LENGTH];
      while(1){
        memset(line, 0, _MAX_LINE_LENGTH);
        if(readLines(line)){
          ubasic_init(line);
          do {
            ubasic_run();
          } while(!ubasic_finished());
        }
      };
    
      return 0;
    
    }
    
    实现write命令的源代码例如以下:

    #include "tokenizer.h"
    #include "stm32f10x_lib.h"
    #include <string.h>
    #include <ctype.h>
    #include <stdlib.h>
    GPIO_TypeDef *gpio_x;
    u16 gpio_pin_x;
    u16 gpio_value;
    struct GPIO_KEYWORD gpio_kt;
    struct PIN_KEYWORD pin_kt;
    
    #define GET_ARRAY_LEN(array,len){len = (sizeof(array) / sizeof(array[0]));}
    
    struct GPIO_KEYWORD {
      char *keyword;
      GPIO_TypeDef *token;
    };
    
    static const struct GPIO_KEYWORD gpio_keywords[] = 
    { { "GPIOA", GPIOA },
        { "GPIOB", GPIOB  },
        { "GPIOC", GPIOC  },
        { "GPIOD", GPIOD  }};
    
    struct PIN_KEYWORD {
      u16 keyword;
      u16 token;;
    };
    
    static const struct PIN_KEYWORD pin_keywords[17] = 
    {  { 0, GPIO_Pin_0 },
        { 1, GPIO_Pin_1 },
        { 2, GPIO_Pin_2 },
        { 3, GPIO_Pin_3 },
        { 4, GPIO_Pin_4 },
        { 5, GPIO_Pin_5 },
        { 6, GPIO_Pin_6 },
        { 7, GPIO_Pin_7 },
        { 8, GPIO_Pin_8 },
        { 9, GPIO_Pin_9 },
        { 10, GPIO_Pin_10 },
        { 11, GPIO_Pin_11 },
        { 12, GPIO_Pin_12 },
        { 13, GPIO_Pin_13 },
        { 14, GPIO_Pin_14 },
        { 15, GPIO_Pin_15 }};
    
    void init_my_statement(){
      gpio_x=NULL;
      gpio_pin_x=NULL;
      gpio_value=NULL;
    }
    
    void put_value(u16 value){
      gpio_value=value;
    }
    
    u16 get_value(){
      return gpio_value;
    }
    
    /**
    **获取GPIO_PIN_X
    **/
    bool put_pin(u16 pin){
        int size=0;
      
        if(gpio_pin_x==NULL){
          GET_ARRAY_LEN(pin_keywords,size);
          if(pin<size){
            gpio_pin_x = pin_keywords[pin].token;
            printf ("------P");printf ("%d
    ",pin);
            return TRUE;
          }
        }
        return FALSE;
    }
    
    u16 get_pin(){
      return gpio_pin_x;
    }
    
    /**
    **获取获取GPIO_X
    **/
    bool put_gpio(char* p){
        int i=0;
        int size=0;
    
        if(gpio_x==NULL){
          GET_ARRAY_LEN(gpio_keywords,size);
          for (i=0; i<size; i++) {
            gpio_kt = gpio_keywords[i];
            if (strncasecmp(p, gpio_kt.keyword, strlen(p)) == 0) {
              printf ("------");printf ("%s
    ",gpio_kt.keyword);
              gpio_x = gpio_kt.token;
              return TRUE;
            }
          }
        }
        return FALSE;
    }
    
    GPIO_TypeDef * get_gpio(){
      return gpio_x;
    }
    
    bool write_gpio(){
      
      //USART1不能被写
      if(gpio_x== GPIOA 
         && (gpio_pin_x==GPIO_Pin_9 
             || gpio_pin_x==GPIO_Pin_10)){
        return FALSE;
      }
      
      GPIO_InitTypeDef GPIO_InitStructure;
    
      GPIO_InitStructure.GPIO_Pin = gpio_pin_x;
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
      GPIO_Init(gpio_x , &GPIO_InitStructure); 
            
      GPIO_WriteBit(gpio_x , gpio_pin_x,(BitAction)gpio_value);                              
      return TRUE;
    }
    



  • 相关阅读:
    https://archive.ics.uci.edu/ml/datasets.php
    实战教程 :使用Python和keras进行文本分类(上)(重要)
    洛谷 P1073 最优贸易
    P2278 [HNOI2003]操作系统
    洛谷P2024 食物链
    模板
    我的博客
    mysql一条sql把表中的男改为女,女改为男
    树的度和结点数的关系
    Spider实例详解
  • 原文地址:https://www.cnblogs.com/yxwkf/p/5030664.html
Copyright © 2020-2023  润新知