21回答

0收藏

在190小红板上实现Trochili平台上的RFID

回答|共 21 个

倒序浏览

21#

火oooo

发表于 2016-6-22 17:55:26 | 只看该作者

分享到:
本帖最后由 火oooo 于 2016-6-22 18:09 编辑

代码讨论区——OLED篇
phoenix_bsp_oled_spi.h
  1. #define OLED_CS_1                                GPIO_SetBits(GPIOB,GPIO_PIN_5)  //
  2. #define OLED_CS_0                                GPIO_ResetBits(GPIOB,GPIO_PIN_5)  //
  3. #define OLED_RST_1                                GPIO_SetBits(GPIOB,GPIO_PIN_4)        //
  4. #define OLED_RST_0                                GPIO_ResetBits(GPIOB,GPIO_PIN_4)        //
  5. #define OLED_DC_1                                GPIO_SetBits(GPIOB,GPIO_PIN_3)        //
  6. #define OLED_DC_0                                GPIO_ResetBits(GPIOB,GPIO_PIN_3)        //
  7. #define OLED_SCLK_1                                GPIO_SetBits(GPIOB,GPIO_PIN_2)  //
  8. #define OLED_SCLK_0                                GPIO_ResetBits(GPIOB,GPIO_PIN_2)  //
  9. #define OLED_SDIN_1                                GPIO_SetBits(GPIOB,GPIO_PIN_1)        //
  10. #define OLED_SDIN_0                                GPIO_ResetBits(GPIOB,GPIO_PIN_1)        //
复制代码
这里是花了最多的时间的地方,因为对GD32F190不了解,以为STM32的位带操作一样可用,结果吃了亐。查看规格书后发现GD的GPIO的地址映射不在起始的1M空间内,所以不能直接用位带操作,之前的位带尝试全部作罢,最后使用了宏定义的形式。当然此处跟模块底层驱动相关,与RTOS无太大关系。

phoenix_bsp_oled_spi.c
  1. RCC_AHBPeriphClock_Enable(RCC_AHBPERIPH_GPIOB, ENABLE);
  2.         /* ????PB1,PB2,PB3,PB4,PB5???ì???? */
  3.         GPIO_InitStructure.GPIO_Pin = GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5;
  4.         GPIO_InitStructure.GPIO_Mode = GPIO_MODE_OUT;        //???ì????
  5.         GPIO_InitStructure.GPIO_OType = GPIO_OTYPE_PP;
  6.         GPIO_InitStructure.GPIO_PuPd = GPIO_PUPD_NOPULL;
  7.         GPIO_InitStructure.GPIO_Speed = GPIO_SPEED_50MHZ;        //????50MHz
  8.          GPIO_Init(GPIOB, &GPIO_InitStructure);                                                //??????
复制代码
仍然是底层驱动,写法与STM32有些许不同,请留意。

colibri_bsp.c
  1. void EvbSetupEntry(void)
  2. {
  3.    EvbUart2Config();
  4.    EvbLedConfig();
  5. //   EvbKeyConfig();
  6.    EvbOledConfig();
  7. }
复制代码
这里开始是RTOS的部分。需要在这里添加OLED的初始化程序,在此例中是EvbOledConfig();,当然不要忘记添加头文件。

example.h
  1. #define EVB_EXAMPLE     SPIOLED   
复制代码
按照飞鸟哥的思路,应用程序需要从这里入口,记得定义一下。

oled.c,此实验的主角,但此处写不下了,放下一楼。
  1. <blockquote>//1. 包含头文件        
复制代码
22#

火oooo

发表于 2016-6-23 21:49:29 | 只看该作者

本帖最后由 火oooo 于 2016-6-23 21:53 编辑

oled.c
  1. //1. 包含头文件        
  2. #include "example.h"
  3. #include "trochili.h"
  4. #include "phoenix_bsp_oled_spi.h"

  5. //2. 预编译开关
  6. #if (EVB_EXAMPLE == SPIOLED)

  7. //3. 三个参数         
  8. //设定栈长宽字节、优先级字节、时间片字节的长度
  9. //Q:怎么设定这个参数的数值?不同的数据会有什么影响?
  10. /* 用户线程参数 */
  11. #define THREAD_OLED_STACK_BYTES   (512)
  12. #define THREAD_OLED_PRIORITY      (5)
  13. #define THREAD_OLED_SLICE         (20)

  14. #define THREAD_REFRESH_STACK_BYTES  (512)
  15. #define THREAD_REFRESH_PRIORITY     (4)
  16. #define THREAD_REFRESH_SLICE        (20)

  17. //4. 定义线程
  18. /* 用户线程定义 */
  19. static TThread ThreadOLED;
  20. //static TThread ThreadOLEDClear;
  21. static TThread ThreadREFRESH;

  22. /* 用户信号量定义 */
  23. static TSemaphore RefreshSemaphore;

  24. //5. 定义线程栈
  25. /* 用户线程栈 */
  26. static TWord ThreadOLEDStack[THREAD_OLED_STACK_BYTES/4];
  27. static TWord ThreadREFRESHStack[THREAD_REFRESH_STACK_BYTES/4];
  28. //static TWord ThreadOLEDClearStack[THREAD_OLED_STACK_BYTES/4];

  29. //6. 定义线程入口函数  线程的主要功能在这里实现。static void ThreadLedEntry(TArgument data)函数就在这个位置
  30. /* 线程OLED的线程函数 */
  31. static void ThreadOLEDEntry(TArgument data)
  32. {
  33.     TState state;
  34.     TError error;        
  35.         u8 t;

  36.         
  37.     while (eTrue)
  38.     {
  39.                                 /* OLED线程以阻塞方式获取信号量,然后显示信息*/
  40.                           state = TclObtainSemaphore(&RefreshSemaphore, TCLO_IPC_WAIT, 0, &error);
  41.         if (state == eSuccess)
  42. //                        while (eTrue)
  43.         {
  44.                                         OLED_ShowString(0,0, "   Phoenix's    ");            //???Phoenix's????
  45.                                         OLED_ShowString(0,16,"UID:            ");                  //Pres:??.?kPa/???
  46.                                         OLED_ShowString(0,32,"                ");                        //Temp:???.?C/????
  47.                                         OLED_ShowString(0,48,"                ");                        //Temp:????h/?????
  48.                                         OLED_Refresh_Gram();                        
  49.                                         EvbUart2WriteStr("wirte finished!");
  50.                                         if((t++)%2)
  51.                                         {
  52.                                                 EvbLedControl(LED1, LED_ON);
  53.                                         }
  54.                                         else
  55.                                         {
  56.                                                 EvbLedControl(LED1, LED_OFF);
  57.                                         }
  58.         }
  59.                                 
  60.     /* OLED线程以阻塞方式获取信号量,然后显示信息*/
  61.      state = TclObtainSemaphore(&RefreshSemaphore, TCLO_IPC_WAIT, 0, &error);
  62. if (state == eSuccess)
  63. //                        while (eTrue)
  64. {
  65.      OLED_Clear();            //
  66.      OLED_Refresh_Gram();
  67.      
  68.      EvbUart2WriteStr("clear finished!\n");
  69.      EvbLedControl(LED1, LED_OFF);
  70. }
  71.     }
  72. }

  73. ///* 线程OLEDClear的线程函数 */
  74. //static void ThreadOLEDClearEntry(TArgument data)
  75. //{
  76. //    TState state;
  77. //    TError error;        
  78. //        
  79. //    while (eTrue)
  80. //    {
  81. //                                /* OLEDClear线程以阻塞方式获取信号量,然后清除信息*/
  82. ////                          state = TclObtainSemaphore(&RefreshSemaphore, TCLO_IPC_WAIT, 0, &error);
  83. ////        if (state == eSuccess)
  84. //                        while (eTrue)
  85. //        {
  86. //                                        OLED_Clear();            //
  87. ////                                        OLED_Refresh_Gram();
  88. //                                       
  89. //                                        EvbUart2WriteStr("clear finished!\n");
  90. //                                        EvbLedControl(LED1, LED_OFF);
  91. //        }
  92. //    }
  93. //}

  94. /* 线程REFRESH的线程函数 */
  95. static void ThreadREFRESHEntry(TArgument data)
  96. {
  97.     TError error;
  98.     TState state;

  99.     while (eTrue)
  100.     {
  101.         /**/
  102. //                                OLED_Refresh_Gram();
  103.                           /* REFRESH线程延时1000ms */
  104.         state =  TclDelayThread(0, TCLM_MLS2TICKS(1000), &error);
  105.         TCLM_ASSERT((state == eSuccess), "");
  106.         TCLM_ASSERT((error == TCLE_THREAD_NONE), "");

  107.         /* REFRESH线程释放信号量 */
  108.         state = TclReleaseSemaphore(&RefreshSemaphore, 0, 0, &error);
  109.         TCLM_ASSERT((state == eSuccess), "");
  110.         TCLM_ASSERT((error == TCLE_IPC_NONE), "");
  111.                         
  112. //                          /* 激活Led设备点亮线程 */
  113. //        state = TclActivateThread(&ThreadOLED, &error);
  114. //        TCLM_ASSERT((state == eSuccess), "");
  115. //        TCLM_ASSERT((error == TCLE_THREAD_NONE), "");
  116. //                        
  117. ////        /* REFRESH线程释放信号量 */
  118. ////        state = TclReleaseSemaphore(&RefreshSemaphore, 0, 0, &error);
  119. ////        TCLM_ASSERT((state == eSuccess), "");
  120. ////        TCLM_ASSERT((error == TCLE_IPC_NONE), "");

  121. //                                OLED_Refresh_Gram();
  122. //        /* 控制线程延时1秒 */
  123. //        state = TclDelayThread(&ThreadREFRESH, TCLM_SEC2TICKS(1), &error);
  124. //        TCLM_ASSERT((state == eSuccess), "");
  125. //        TCLM_ASSERT((error == TCLE_THREAD_NONE), "");

  126. //        /* 休眠Led设备点亮线程 */
  127. //        state = TclDeactivateThread(&ThreadOLED, &error);
  128. //        TCLM_ASSERT((state == eSuccess), "");
  129. //        TCLM_ASSERT((error == TCLE_THREAD_NONE), "");

  130. //        /* 激活Led设备熄灭线程 */
  131. //        state = TclActivateThread(&ThreadOLEDClear, &error);
  132. //        TCLM_ASSERT((state == eSuccess), "");
  133. //        TCLM_ASSERT((error == TCLE_THREAD_NONE), "");
  134. //                                
  135. ////                                /* REFRESH线程释放信号量 */
  136. ////        state = TclReleaseSemaphore(&RefreshSemaphore, 0, 0, &error);
  137. ////        TCLM_ASSERT((state == eSuccess), "");
  138. ////        TCLM_ASSERT((error == TCLE_IPC_NONE), "");

  139. //                                OLED_Refresh_Gram();
  140. //        /* 控制线程延时1秒 */
  141. //        state = TclDelayThread(&ThreadREFRESH, TCLM_SEC2TICKS(1), &error);
  142. //        TCLM_ASSERT((state == eSuccess), "");
  143. //        TCLM_ASSERT((error == TCLE_THREAD_NONE), "");

  144. //        /* 休眠Led设备熄灭线程 */
  145. //        state = TclDeactivateThread(&ThreadOLEDClear, &error);
  146. //        TCLM_ASSERT((state == eSuccess), "");
  147. //        TCLM_ASSERT((error == TCLE_THREAD_NONE), "");
  148.     }
  149. }

  150. //7. 定义应用入口函数  系统调用此应用,从而对线程进行处理
  151. /* 用户应用入口函数 */
  152. static void AppSetupEntry(void)
  153. {
  154.     TError error;
  155.     TState state;
  156.         
  157.     /* 初始化信号量 */
  158.     state = TclInitSemaphore(&RefreshSemaphore, 0, 1, TCLP_IPC_DUMMY, &error);
  159.     TCLM_ASSERT((state == eSuccess), "");
  160.     TCLM_ASSERT((error == TCLE_IPC_NONE), "");
  161.         
  162.     /* 初始化OLED设备线程 */
  163.     state = TclInitThread(&ThreadOLED,
  164.                           &ThreadOLEDEntry, (TArgument)0,
  165.                           ThreadOLEDStack, THREAD_OLED_STACK_BYTES,
  166.                           THREAD_OLED_PRIORITY, THREAD_OLED_SLICE,
  167.                           &error);
  168.     TCLM_ASSERT((state == eSuccess), "");
  169.     TCLM_ASSERT((error == TCLE_THREAD_NONE), "");

  170. //    /* 初始化OLEDClear设备线程 */
  171. //    state = TclInitThread(&ThreadOLEDClear,
  172. //                          &ThreadOLEDClearEntry, (TArgument)0,
  173. //                          ThreadOLEDClearStack, THREAD_OLED_STACK_BYTES,
  174. //                          THREAD_OLED_PRIORITY, THREAD_OLED_SLICE,
  175. //                          &error);
  176. //    TCLM_ASSERT((state == eSuccess), "");
  177. //    TCLM_ASSERT((error == TCLE_THREAD_NONE), "");



  178.     /* 初始化REFRESH线程 */
  179.     state = TclInitThread(&ThreadREFRESH,
  180.                           &ThreadREFRESHEntry, (TArgument)0,
  181.                           ThreadREFRESHStack, THREAD_REFRESH_STACK_BYTES,
  182.                           THREAD_REFRESH_PRIORITY, THREAD_REFRESH_SLICE,
  183.                           &error);
  184.     TCLM_ASSERT((state == eSuccess), "");
  185.     TCLM_ASSERT((error == TCLE_THREAD_NONE), "");

  186.     /* 激活REFRESH线程 */
  187.     state = TclActivateThread(&ThreadREFRESH, &error);
  188.     TCLM_ASSERT((state == eSuccess), "");
  189.     TCLM_ASSERT((error == TCLE_THREAD_NONE), "");
  190.                
  191.     /* 激活OLED线程 */
  192.     state = TclActivateThread(&ThreadOLED, &error);
  193.     TCLM_ASSERT((state == eSuccess), "");
  194.     TCLM_ASSERT((error == TCLE_THREAD_NONE), "");
  195.                
  196. //    /* 激活OLEDClear线程 */
  197. //    state = TclActivateThread(&ThreadOLEDClear, &error);
  198. //    TCLM_ASSERT((state == eSuccess), "");
  199. //    TCLM_ASSERT((error == TCLE_THREAD_NONE), "");

  200.                 EvbUart2WriteStr("\nAPP INIT finished!\n");
  201. }

  202. //8. 定义main函数
  203. /* 处理器BOOT之后会调用main函数,必须提供 */
  204. int main(void)
  205. {
  206. /* 注册各个内核函数,启动内核 */
  207. TclStartKernel(&AppSetupEntry,
  208. &CpuSetupEntry,
  209. &EvbSetupEntry,
  210. &EvbTraceEntry);
  211. return 1;
  212. }

  213. #endif
复制代码
还记得我们说过的8个结构吗?
1. 包含头文件        
2. 预编译开关
3. 三个参数          设定栈长宽字节、优先级字节、时间片字节的长度
4. 定义线程
5. 定义线程栈
6. 定义线程入口函数  线程的主要功能在这里实现
7. 定义应用入口函数  系统调用此应用,从而对线程进行处理
8. 定义main函数
我们逐个来看。



23#

火oooo

发表于 2016-6-23 22:02:19 | 只看该作者

本帖最后由 火oooo 于 2016-6-23 22:28 编辑

1. 包含头文件        
在这里添加新增加功能模块的头文件,当然这里指的是#include "phoenix_bsp_oled_spi.h"。
2. 预编译开关
在example.h中设置对应的名字,这里是EVB_EXAMPLE == SPIOLED。
3. 三个参数          设定栈长宽字节、优先级字节、时间片字节的长度
依葫芦画瓢,还没有吃透个中参数的意思,但跟后面的线程数目可以不等。
4. 定义线程
这里设定两个线程,ThreadOLED与ThreadREFRESH。其中ThreadOLED为显示线程,ThreadREFRESH为控制线程。至于名字为什么是ThreadREFRESH,这个是有其原因的,也因如此才会有前面“多打Printf”的说法,具体故事后面再讲。
5. 定义线程栈
依葫芦画瓢,这个数目与线程数目一致。
6. 定义线程入口函数  线程的主要功能在这里实现
这里是最能体现你的设计思想的地方,模块的功能全部在这里体现。让我们详细来说,对照着头面的代码。
这里使用的是信号量的方式。控制线程ThreadREFRESH延时1s,然后释放信号量;接着OLED线程以阻塞方式获取信号量,显示需要显示的内容;1s时间到达,控制线程ThreadREFRESH再延时1s,然后释放信号量;接着OLED线程以阻塞方式获取信号量,清除显示;1s时间到达,再进入下一次循环,以此实现OLED显示与清屏。
7. 定义应用入口函数  系统调用此应用,从而对线程进行处理
对各线程进行初始化,并激活需要激活的线程。 这里需要激活的线程是ThreadREFRESH与ThreadOLED。
8. 定义main函数
依葫芦画瓢。
您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

站长推荐上一条 /3 下一条