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

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

[vb] view plaincopyprint?
  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 plaincopyprint?
  1. write "gpioa",p,v

如下图:

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

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

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

实现write命令的源码如下:

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

Basic脚本解释器移植到STM32相关推荐

  1. stm32 移植java_把Lua移植到stm32上,效果不错! (amoBBS 阿莫电子论坛)

    因为我们产品的需要满足不同行业需求,所以一直在寻找一个脚本语言,以便灵活配置. 前段时间还自己花时间去实现一个C语言解释器,看了一堆编译原理的东西,以及虚拟机等,头都搞大了,把基本功能实现了,但总是不 ...

  2. 嵌入式JavaScript脚本解释器的研究与实现

    论文标题:嵌入式JavaScript脚本解释器的研究与实现 The Research and Implementation of an Embedded JavaScript Interpreter ...

  3. #! 脚本解释器(如何不加node 直接执行js文件)

    #! 脚本解释器(如何不加node 直接执行js文件) 内容来源:https://blog.csdn.net/liukai6/article/details/80071916 #!是特殊的表示符,其后 ...

  4. harmonyos能否移植到MCU,HarmonyOS(LiteOs_m) 官方例程移植到STM32初体验

    HarmonyOS(LiteOs_m) 官方例程移植到STM32初体验 硬件平台 基于正点原子战舰V3开发板 MCU:STM32F103ZET6 片上SRAM大小:64KBytes 片上FLASH大小 ...

  5. 如何使用 Visual Basic 脚本添加默认打印机

    本文介绍如何使用 Visual Basic 脚本添加打印机并使其成为默认打印机. 如果打印机不是本地连接到 LPT.COM 或 USB 端口,终端服务上的"Windows 打印机映射&quo ...

  6. julia语言 python解释器_继 Python 解释器移植到 Firefox 后,Mozilla 现在想支持 Julia 和 R...

    Mozilla 正在资助一个将 Julia 编程语言引入 Firefox 和一般浏览器环境的项目. Mozilla 在上周五宣布,该项目在 2019 年上半年获得了 Mozilla Research ...

  7. 记一个脚本解释器的开发

    最近可以有1个月左右的空闲,可以稍微整理一下这个脚本解释器的开发过程. 一.缘由 2014年左右,我们使用AIR技术,开发了一个3D战争类型的手游.那时候手游开发技术主要是cocos2d,unity, ...

  8. 基于Linux的kfifo移植到STM32(支持os的互斥访问)

    基于Linux的kfifo移植到STM32(支持os的互斥访问) 声明:本文为杰杰原创,转载请说明出处 https://blog.csdn.net/jiejiemcu/article/details/ ...

  9. 12864移植到STM32平台

    利用串口方式将原本51单片机上的串口程序移植到STM32上,调试了两天终于可以显示了 1. 排查IO的初始化是否有问题,在STM32平台上需要对IO口时钟使能,IO口模式配置,一些特殊的管脚还需要做特 ...

最新文章

  1. origin9语言设置中文_英雄联盟手游怎么设置繁体 LOL手游繁中设置方法?_英雄联盟手游...
  2. ADO.NET Entity Framework 简介
  3. Ubuntu终端Terminal常用快捷键
  4. 2021年图机器学习有哪些新突破?麦吉尔大学博士后一文梳理展望领域趋势
  5. Native与H5交互的一些解决方法
  6. Fibonacci递归非递归方法
  7. java字符集编码是,java字符集与编码有关问题
  8. ICCV 2019 | 上海交大MVIG团队提出InstaBoost,换个dataloader函数, COCO提升3mAP
  9. mysql报错01427_ORA-01427问题的分析和解决
  10. “我恨Google无人车”
  11. 加速失败远程计算机不能反应,2008 R2 SP1远程桌面如何开启GPU加速?不讨论虚拟机...
  12. 《团队-科学计算器-项目进度》
  13. 用装饰器来进行登录验证
  14. 【基础教程】基于matlab图像处理(表示方法+数据结构+基本格式+类型转换+读取+点运算+代数运算)【含Matlab源码 834期】
  15. java jdbc 参数 转义_jdbc URL中的各个参数详解
  16. linux环境libudev安装,树莓派 3B 上安装 libnfc 配合 acr122u 读取 nfc
  17. 《大数据技术原理与应用》—— 提纲
  18. jad反编译成java,Jad java反编译指令
  19. python无穷大怎么表示_python如何表示无穷大
  20. linux中mysql启动时遇到MySql server PID file cound not be found

热门文章

  1. 【运筹学】表上作业法 ( 示例 | 使用 “ 最小元素法 “ 找初始基可行解 )
  2. 【Android 安全】DEX 加密 ( Application 替换 | 获取 ContextImpl、ActivityThread、LoadedApk 类型对象 | 源码分析 )
  3. 【Android 内存优化】Android 原生 API 图片压缩原理 ( 图片质量压缩方法 | 查找 Java 源码中的 native 方法对应的 C++ 源码 )
  4. 【Android 应用开发】BluetoothAdapter解析
  5. C#文件夹权限操作工具类
  6. java 中文及特殊字符校验
  7. linux PHP 编译安装参数详解
  8. movsb movsw movsd 指令详解
  9. 在 word 中 mathType 菜单灰色,无法使用
  10. moveit!功能包安装问题