Basic脚本解释器移植到STM32

上次讲了LUA移植到STM32,这次讲讲Basic脚本解释器移植到STM32。在STM32上跑Basic脚本,同样可以跟穿戴设备结合,也可以作为初学者学习MCU的入门工具,当然前提是有人做好Basic的STM32交互实现。这里使用的是uBasic开源脚本解释器(http://dunkels.com/adam/ubasic/),不过uBasic不支持完整的Basic算法,所以用起来略费心,如果有好的Basic开源脚本解释器,ANSI-C实现的,欢迎推荐。。。

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

[vb]  view plain copy print ?
  1. 10 v=1  
  2. 20 for p = 4 to 7  
  3. 40 write "gpioa",p,v  
  4. 50 next p  
  5. 60 if v=0 then goto 10  
  6. 70 if v=1 then v=0  
  7. 80 goto 20  
  8. run  
实现的功能是同时把4个LED灯同时开后再同时关,通过自定义的命令 write来实现,p是IO脚,v是IO的数值。
[vb]  view plain copy print ?
  1. write "gpioa",p,v  

如下图:

本文代码可以到这里下载http://download.csdn.net/detail/hellogv/7391265。

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

[cpp]  view plain copy print ?
  1. #include "stm32f10x_lib.h"  
  2. #include   
  3. #include "stdio.h"  
  4. #include   
  5. #include   
  6. #include "ubasic.h"  
  7.   
  8. /******************************************************************************* 
  9.  * 函数名  : RCC_Configuration 
  10.  * 函数描述  : 设置系统各部分时钟 
  11.  *******************************************************************************/  
  12.   
  13. void RCC_Configuration(void) {  
  14.   /* 定义枚举类型变量 HSEStartUpStatus */  
  15.   ErrorStatus HSEStartUpStatus;  
  16.   
  17.   /* 复位系统时钟设置*/  
  18.   RCC_DeInit();  
  19.   /* 开启HSE*/  
  20.   RCC_HSEConfig(RCC_HSE_ON );  
  21.   /* 等待HSE起振并稳定*/  
  22.   HSEStartUpStatus = RCC_WaitForHSEStartUp();  
  23.   /* 判断HSE起是否振成功,是则进入if()内部 */  
  24.   if (HSEStartUpStatus == SUCCESS) {  
  25.     /* 选择HCLK(AHB)时钟源为SYSCLK 1分频 */  
  26.     RCC_HCLKConfig(RCC_SYSCLK_Div1 );  
  27.     /* 选择PCLK2时钟源为 HCLK(AHB) 1分频 */  
  28.     RCC_PCLK2Config(RCC_HCLK_Div1 );  
  29.     /* 选择PCLK1时钟源为 HCLK(AHB) 2分频 */  
  30.     RCC_PCLK1Config(RCC_HCLK_Div2 );  
  31.     /* 设置FLASH延时周期数为2 */  
  32.     FLASH_SetLatency(FLASH_Latency_2 );  
  33.     /* 使能FLASH预取缓存 */  
  34.     FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable );  
  35.     /* 选择锁相环(PLL)时钟源为HSE 1分频,倍频数为9,则PLL输出频率为 8MHz * 9 = 72MHz */  
  36.     RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9 );  
  37.     /* 使能PLL */  
  38.     RCC_PLLCmd(ENABLE);  
  39.     /* 等待PLL输出稳定 */  
  40.     while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY ) == RESET)  
  41.       ;  
  42.     /* 选择SYSCLK时钟源为PLL */  
  43.     RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK );  
  44.     /* 等待PLL成为SYSCLK时钟源 */  
  45.     while (RCC_GetSYSCLKSource() != 0x08)  
  46.       ;  
  47.   }  
  48.   
  49.   /* 开启USART1和GPIOA时钟 */  
  50.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA,  
  51.       ENABLE);  
  52. }  
  53.   
  54. /******************************************************************************* 
  55.  * 函数名      : GPIO_Configuration 
  56.  * 函数描述      : 设置各GPIO端口功能 
  57.  *******************************************************************************/  
  58.   
  59. void GPIO_Configuration(void) {  
  60.   /* 定义GPIO初始化结构体 GPIO_InitStructure */  
  61.   GPIO_InitTypeDef GPIO_InitStructure;  
  62.   
  63.   /* 设置USART1的Tx脚(PA.9)为第二功能推挽输出功能 */  
  64.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;  
  65.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  
  66.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  
  67.   GPIO_Init(GPIOA, &GPIO_InitStructure);  
  68.   
  69.   /* 设置USART1的Rx脚(PA.10)为浮空输入脚 */  
  70.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;  
  71.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;  
  72.   GPIO_Init(GPIOA, &GPIO_InitStructure);  
  73. }  
  74.   
  75. /******************************************************************************* 
  76.  * 函数名      : USART_Configuration 
  77.  * 函数描述      : 设置USART1 
  78.  *******************************************************************************/  
  79.   
  80. void USART_Configuration(void) {  
  81.   /* 定义USART初始化结构体 USART_InitStructure */  
  82.   USART_InitTypeDef USART_InitStructure;  
  83.   /* 定义USART初始化结构体 USART_ClockInitStructure */  
  84.   USART_ClockInitTypeDef USART_ClockInitStructure;  
  85.   
  86.   /*  波特率为115200bps; 
  87.    *  8位数据长度; 
  88.    *  1个停止位,无校验; 
  89.    *  禁用硬件流控制; 
  90.    *  禁止USART时钟; 
  91.    *  时钟极性低; 
  92.    *  在第2个边沿捕获数据 
  93.    *  最后一位数据的时钟脉冲不从 SCLK 输出; 
  94.    */  
  95.   
  96.   USART_ClockInitStructure.USART_Clock = USART_Clock_Disable;  
  97.   USART_ClockInitStructure.USART_CPOL = USART_CPOL_Low;  
  98.   USART_ClockInitStructure.USART_CPHA = USART_CPHA_2Edge;  
  99.   USART_ClockInitStructure.USART_LastBit = USART_LastBit_Disable;  
  100.   USART_ClockInit(USART1, &USART_ClockInitStructure);  
  101.   
  102.   USART_InitStructure.USART_BaudRate = 9600;  
  103.   USART_InitStructure.USART_WordLength = USART_WordLength_8b;  
  104.   USART_InitStructure.USART_StopBits = USART_StopBits_1;  
  105.   USART_InitStructure.USART_Parity = USART_Parity_No ;  
  106.   USART_InitStructure.USART_HardwareFlowControl =USART_HardwareFlowControl_None;  
  107.   USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;  
  108.   USART_Init(USART1, &USART_InitStructure);  
  109.   
  110.   /* 使能USART1 */  
  111.   USART_Cmd(USART1, ENABLE);  
  112. }  
  113.   
  114. int fputc(int ch, FILE *f) {  
  115.   USART_SendData(USART1, (u8) ch);  
  116.   while (USART_GetFlagStatus(USART1, USART_FLAG_TC ) == RESET);  
  117.   return ch;  
  118. }  
  119.   
  120. int getKey(void) {  
  121.   while (!(USART1 ->SR & USART_FLAG_RXNE ));  
  122.   return ((int) (USART1 ->DR & 0x1FF));  
  123. }  
  124.   
  125. /******************************************************************************* 
  126.  * 函数名      : readLine 
  127.  * 函数描述      : 从串口读取Basic代码 
  128.  *******************************************************************************/  
  129. bool readLines(char *s) {  
  130.   bool isString = FALSE; //判断是否字符串  
  131.   char ch;  
  132.   char *p = s;  
  133.     
  134.   if(*p!='\0')  
  135.     return FALSE;  
  136.     
  137.   while (1) {  
  138.     ch = getKey();  
  139.     if (ch == '\"') { //检测到字符串  
  140.       isString = !isString;  
  141.     }  
  142.   
  143.     if (ch == '\r'//屏蔽'\r'这个字符  
  144.       continue;  
  145.     else {  
  146.       if (isString) //不改变代码中字符串的大小写  
  147.         *p++ = ch;  
  148.       else //关键字都转为小写  
  149.         *p++ = tolower(ch);  
  150.     }  
  151.       
  152.     if (*(p-3) == 'r'  
  153.           &&*(p-2)=='u'  
  154.           &&*(p-1)=='n'){ //run表示程序结束  
  155.       *(p-3) = '\0';  
  156.       break;  
  157.     }  
  158.   }  
  159.   return TRUE;  
  160. }  
  161.   
  162. #define _MAX_LINE_LENGTH 256  
  163. int main(void) {  
  164.   /* 设置系统时钟 */  
  165.   RCC_Configuration();  
  166.   /* 设置GPIO端口 */  
  167.   GPIO_Configuration();  
  168.   /* 设置USART */  
  169.   USART_Configuration();  
  170.   
  171.   char line[_MAX_LINE_LENGTH];  
  172.   while(1){  
  173.     memset(line, 0, _MAX_LINE_LENGTH);  
  174.     if(readLines(line)){  
  175.       ubasic_init(line);  
  176.       do {  
  177.         ubasic_run();  
  178.       } while(!ubasic_finished());  
  179.     }  
  180.   };  
  181.   
  182.   return 0;  
  183.   
  184. }  
实现write命令的源码如下:

[cpp]  view plain copy print ?
  1. #include "tokenizer.h"  
  2. #include "stm32f10x_lib.h"  
  3. #include   
  4. #include   
  5. #include   
  6. GPIO_TypeDef *gpio_x;  
  7. u16 gpio_pin_x;  
  8. u16 gpio_value;  
  9. struct GPIO_KEYWORD gpio_kt;  
  10. struct PIN_KEYWORD pin_kt;  
  11.   
  12. #define GET_ARRAY_LEN(array,len){len = (sizeof(array) / sizeof(array[0]));}  
  13.   
  14. struct GPIO_KEYWORD {  
  15.   char *keyword;  
  16.   GPIO_TypeDef *token;  
  17. };  
  18.   
  19. static const struct GPIO_KEYWORD gpio_keywords[] =   
  20. { { "GPIOA", GPIOA },  
  21.     { "GPIOB", GPIOB  },  
  22.     { "GPIOC", GPIOC  },  
  23.     { "GPIOD", GPIOD  }};  
  24.   
  25. struct PIN_KEYWORD {  
  26.   u16 keyword;  
  27.   u16 token;;  
  28. };  
  29.   
  30. static const struct PIN_KEYWORD pin_keywords[17] =   
  31. {  { 0, GPIO_Pin_0 },  
  32.     { 1, GPIO_Pin_1 },  
  33.     { 2, GPIO_Pin_2 },  
  34.     { 3, GPIO_Pin_3 },  
  35.     { 4, GPIO_Pin_4 },  
  36.     { 5, GPIO_Pin_5 },  
  37.     { 6, GPIO_Pin_6 },  
  38.     { 7, GPIO_Pin_7 },  
  39.     { 8, GPIO_Pin_8 },  
  40.     { 9, GPIO_Pin_9 },  
  41.     { 10, GPIO_Pin_10 },  
  42.     { 11, GPIO_Pin_11 },  
  43.     { 12, GPIO_Pin_12 },  
  44.     { 13, GPIO_Pin_13 },  
  45.     { 14, GPIO_Pin_14 },  
  46.     { 15, GPIO_Pin_15 }};  
  47.   
  48. void init_my_statement(){  
  49.   gpio_x=NULL;  
  50.   gpio_pin_x=NULL;  
  51.   gpio_value=NULL;  
  52. }  
  53.   
  54. void put_value(u16 value){  
  55.   gpio_value=value;  
  56. }  
  57.   
  58. u16 get_value(){  
  59.   return gpio_value;  
  60. }  
  61.   
  62. /** 
  63. **获取GPIO_PIN_X 
  64. **/  
  65. bool put_pin(u16 pin){  
  66.     int size=0;  
  67.     
  68.     if(gpio_pin_x==NULL){  
  69.       GET_ARRAY_LEN(pin_keywords,size);  
  70.       if(pin
  71.         gpio_pin_x = pin_keywords[pin].token;  
  72.         printf ("------P");printf ("%d\r\n",pin);  
  73.         return TRUE;  
  74.       }  
  75.     }  
  76.     return FALSE;  
  77. }  
  78.   
  79. u16 get_pin(){  
  80.   return gpio_pin_x;  
  81. }  
  82.   
  83. /** 
  84. **获取获取GPIO_X 
  85. **/  
  86. bool put_gpio(char* p){  
  87.     int i=0;  
  88.     int size=0;  
  89.   
  90.     if(gpio_x==NULL){  
  91.       GET_ARRAY_LEN(gpio_keywords,size);  
  92.       for (i=0; i
  93.         gpio_kt = gpio_keywords[i];  
  94.         if (strncasecmp(p, gpio_kt.keyword, strlen(p)) == 0) {  
  95.           printf ("------");printf ("%s\r\n",gpio_kt.keyword);  
  96.           gpio_x = gpio_kt.token;  
  97.           return TRUE;  
  98.         }  
  99.       }  
  100.     }  
  101.     return FALSE;  
  102. }  
  103.   
  104. GPIO_TypeDef * get_gpio(){  
  105.   return gpio_x;  
  106. }  
  107.   
  108. bool write_gpio(){  
  109.     
  110.   //USART1不能被写  
  111.   if(gpio_x== GPIOA   
  112.      && (gpio_pin_x==GPIO_Pin_9   
  113.          || gpio_pin_x==GPIO_Pin_10)){  
  114.     return FALSE;  
  115.   }  
  116.     
  117.   GPIO_InitTypeDef GPIO_InitStructure;  
  118.   
  119.   GPIO_InitStructure.GPIO_Pin = gpio_pin_x;  
  120.   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  
  121.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  
  122.   GPIO_Init(gpio_x , &GPIO_InitStructure);   
  123.           
  124.   GPIO_WriteBit(gpio_x , gpio_pin_x,(BitAction)gpio_value);                                
  125.   return TRUE;  
  126. }  


你可能感兴趣的:(Basic脚本解释器移植到STM32)