查看: 1328|回复: 3

[经验] 基于一块测线板,让你从STM8S从入门到提高

[复制链接]
  • TA的每日心情
    开心
    2019-11-4 13:48
  • 签到天数: 14 天

    连续签到: 1 天

    [LV.3]偶尔看看II

    发表于 2020-6-18 15:03:53 | 显示全部楼层 |阅读模式
    分享到:
    我刚刚使用STM8S几个月,从刚开始到现在会使用,在这过程中也走了很多的弯路,浪费了许多时间。我看到也有一些刚接触STM8的同学和我刚开始一样,对于入门STM8无从下手。我在这里把我入门的过程给分享出来,希望能对想入门STM8S的同学有所帮助。根据我个人的学习经历,感觉初学者最需要的是从一个实际的项目入手,让初学者在不熟悉其全部理论的情况下也可以把东西做出来,然后再回过头来去理解其中的全部原理。我的STM8入门是从一个测线板开始的,我把我的学习过程和其中碰到的问题全部写了来。
       1 准备工作: 一块STM8学习板,编程软件,数据手册,参考手册, 一颗坚不可崔的决心。
       想做成一个东西,兴趣、压力、动力,这几点非常重要,我希望朋友们在学习STM8之前能给自己找一个学习的理由,绝对会事办功倍,我当初给自己设了一个理由,我学会了STM8S,就能够涨工资,然后就可以找到个漂亮的女朋友。学习STM8有着他天然的优势,首先这芯片价格便宜(香蕉超市最便宜卖2块2,它最便宜的只要1块5);其次,学习它只需要用到我们最喜爱的语言(chinese Simple);再次它的官方资料非常多,官方库的程序很直观,不像飞思卡尔什么的,各种秀操作




    我的板子是我自己做的,上面有一个四位共阴数码管,8个LED和8个按键,一个蜂鸣器,一组测12根排线通断的接线口,一组用RS485芯片引出来的串口。我的板子的原理图和PCB我会在附件中提供。想要学习好STM8S单片机,大家也最好能有一块开发板,淘宝上卖的很便宜,少吃点香蕉就可以买到了,卖家还提供有很多的例程,个人建议大家买个简单的板子,有条件的话,建议自己做一个。
        目前STM8S的编程软件有 IAR FOR STM8  和官方的STVD ,个人强列推荐IAR FOR STM8,STVD比较难用,我两者都用过,现在一直在用 IAR FOR STM8 1.3(这个软件大家自己网上搜了,比超市里的香蕉还要多)
       我的板子用的芯片是STM8S207RB ,对应的数据手册和参考手册在这里直接下载。个和第二个就是(RM0016 参考手册 和 DS5839 数据手册)。数据手册是介绍该芯片里面有哪些资源、片上外设供大家使用,以及它的电气参数(相当于超市里面挂在香蕉前面的牌子)。而参考手册刚是介绍如使用编程这款芯片了(其实这款芯片毕竟是8位单片机,入门也相对比较简单,祝大家早日能像吃香蕉一样简单的用它)。我的原理图和PCB是用 altium designer 9.3画的。
      
       如果你用到的芯片也是STM8S207RB的话,直接用我的附件的中的 工程模板就可以了。代码库中有帮助文挡和官方例程。
       最后还有个福利,标准外围库,中文函数生成器,在附件中(STM8S真是好,这也能有! ! ! 被天上的馅饼砸中了,满满的都是幸福! ! !)









    首先编程软件的安装,开发环境的搭建,以及想自己建立工程模板的同学们,请参考附件。我在这里介绍如何驱动我的板子上面的LED。
      从原理图上可以看出,我的8颗LED连接PG0~PG7上面,公共端连接在ULN2003A上,由PE0端口驱动。如果我想要第 1 个小灯点亮,只要 PG = 0x01 , PE0 = 1 即可。
      如查想做个LED的闪烁效果,大家可以在MAIN文件中加上如下一段简单的程序

    void delay(unsigned int t)   
    {
      unsigned char i;
      while(t--)
      {
        for(i=0;i<250;i++);
      }
    }

    void main(void)
    {
       GPIO_DeInit(GPIOG);  //复位G端口寄存器
       GPIO_DeInit(GPIOE);  //复位E端口寄存器
       
       GPIO_Init(GPIOG,GPIO_PIN_ALL,GPIO_MODE_OUT_PP_LOW_SLOW); //初始化GPIOG为推挽 低速 输出
                                                                                                                    //初始电平为低电平
       GPIO_Init(GPIOE,GPIO_PIN_0,GPIO_MODE_OUT_PP_LOW_SLOW);   //初始化GPIOE0为推挽 低速 输出
                                                                                                                   //初始电平为低电平
       
       GPIO_WriteHigh(GPIOE, GPIO_PIN_0);   //打开LED的公共端  即 PE0 = 1
      /* Infinite loop */
      while (1)
      {
        GPIO_WriteHigh(GPIOG, GPIO_PIN_0);   //点亮第1个LED   即PG0 = 1
        delay(1000);                                          //延时一小段时间
        GPIO_WriteLow(GPIOG, GPIO_PIN_0);   //关闭每1个LED   即PG0 = 0
        delay(1000);                                          //延时一小段时间
      }
    }

    在这段程序中,单片机使用的是上电复位后默认的初始化(内部16M的参考时钟8分频,即2MHz作为系统主频)。

    GPIO_Init(GPIOG,GPIO_PIN_ALL,GPIO_MODE_OUT_PP_LOW_SLOW);函数的原型如下
    void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_Pin_TypeDef GPIO_Pin, GPIO_Mode_TypeDef GPIO_Mode)
    它的功能是初始化一个端口的指定引脚为某种状态

    这个函数它有三个参数,
    第一个 GPIO_TypeDef*   GPIOx    ( 选择端口)
    其中这个 GPIOx   可以替换成 GPIOA 、 GPIOB、 GIPOC、GPIOD、GPIOE、GPIOF

    第二个参数是  GPIO_Pin_TypeDef   GPIO_Pin      (选择引脚)  
    其中这个 GPIO_Pin 可以替换成下面这些
      GPIO_PIN_0    = ((uint8_t)0x01),  /*!< Pin 0 selected */
      GPIO_PIN_1    = ((uint8_t)0x02),  /*!< Pin 1 selected */
      GPIO_PIN_2    = ((uint8_t)0x04),  /*!< Pin 2 selected */
      GPIO_PIN_3    = ((uint8_t)0x08),   /*!< Pin 3 selected */
      GPIO_PIN_4    = ((uint8_t)0x10),  /*!< Pin 4 selected */
      GPIO_PIN_5    = ((uint8_t)0x20),  /*!< Pin 5 selected */
      GPIO_PIN_6    = ((uint8_t)0x40),  /*!< Pin 6 selected */
      GPIO_PIN_7    = ((uint8_t)0x80),  /*!< Pin 7 selected */
      GPIO_PIN_LNIB = ((uint8_t)0x0F),  /*!< Low nibble pins selected */
      GPIO_PIN_HNIB = ((uint8_t)0xF0),  /*!< High nibble pins selected */
      GPIO_PIN_ALL  = ((uint8_t)0xFF)   /*!< All pins selected */

    第三个参数是  GPIO_Mode_TypeDef   GPIO_Mode  (选择模式)
    其中这个 GPIO_Mode 可以替换成下面这些
    GPIO_MODE_IN_FL_NO_IT      = (uint8_t)0x00,  /*!< Input floating, no external interrupt */
      GPIO_MODE_IN_PU_NO_IT      = (uint8_t)0x40,  /*!< Input pull-up, no external interrupt */
      GPIO_MODE_IN_FL_IT         = (uint8_t)0x20,  /*!< Input floating, external interrupt */
      GPIO_MODE_IN_PU_IT         = (uint8_t)0x60,  /*!< Input pull-up, external interrupt */
      GPIO_MODE_OUT_OD_LOW_FAST  = (uint8_t)0xA0,  /*!< Output open-drain, low level, 10MHz */
      GPIO_MODE_OUT_PP_LOW_FAST  = (uint8_t)0xE0,  /*!< Output push-pull, low level, 10MHz */
      GPIO_MODE_OUT_OD_LOW_SLOW  = (uint8_t)0x80,  /*!< Output open-drain, low level, 2MHz */
      GPIO_MODE_OUT_PP_LOW_SLOW  = (uint8_t)0xC0,  /*!< Output push-pull, low level, 2MHz */
      GPIO_MODE_OUT_OD_HIZ_FAST  = (uint8_t)0xB0,  /*!< Output open-drain, high-impedance level,10MHz */
      GPIO_MODE_OUT_PP_HIGH_FAST = (uint8_t)0xF0,  /*!< Output push-pull, high level, 10MHz */
      GPIO_MODE_OUT_OD_HIZ_SLOW  = (uint8_t)0x90,  /*!< Output open-drain, high-impedance level, 2MHz */
      GPIO_MODE_OUT_PP_HIGH_SLOW = (uint8_t)0xD0   /*!< Output push-pull, high level, 2MHz


    GPIO_TypeDef 是一个结构体类型 ,它的定义如下: (这个对于初学单片机的同学可以不用关心)
    typedef struct GPIO_struct
    {
      __IO uint8_t ODR; // 数据输出寄存器
      __IO uint8_t IDR; //数据输入寄存器
      __IO uint8_t DDR; //端口方向寄存器  
      __IO uint8_t CR1; //控制寄存器1
      __IO uint8_t CR2; //控制寄存器2
    }
    GPIO_TypeDef;

    #define GPIOA ((GPIO_TypeDef *) GPIOA_BaseAddress)   //这里是为从 GPIOA_BaseAddress 到  GPIOA_BaseAddress + 5 这段地址                                                                                                 //取个名字叫GPIOA  ,STM8所的寄存器都是差不多这样定义的
    #define GPIOB ((GPIO_TypeDef *) GPIOB_BaseAddress)
    #define GPIOC ((GPIO_TypeDef *) GPIOC_BaseAddress)
    #define GPIOD ((GPIO_TypeDef *) GPIOD_BaseAddress)
    #define GPIOE ((GPIO_TypeDef *) GPIOE_BaseAddress)
    #define GPIOF ((GPIO_TypeDef *) GPIOF_BaseAddress)




    STM8s定时器的使用程序


      STM8S包含有三种定时器,高级定时器,通用定时器和基本定时器,这三种定时器在功能上是包含关系的。在这里做一段最简单的1ms的定时功能。
      static void MCU_TIM2_Init(void)  //定时器2 1ms中断初始化
    {
      TIM2_DeInit();                                                                 //复位所有寄存器值,这一步呢可选,为了产品稳定性,最好还是选上
      TIM2_TimeBaseInit(TIM2_PRESCALER_1, 0x07d0);          //2M 内部时钟,一分频 2000
      TIM2_UpdateDisableConfig(DISABLE);                             //允许更新    即是在每一次定时器溢出之后,会自动更新计数器
      TIM2_UpdateRequestConfig(TIM2_UPDATESOURCE_REGULAR);  //只允许规则请求更新,即是只允许定时器溢出更新
      TIM2_ITConfig(TIM2_IT_UPDATE, ENABLE);                //打开定时器溢出中断
      TIM2_Cmd(ENABLE);                                                   //启动定时器
    }

    通过上面的一段程序即实现1ms 的定时功能 :我的这个示例是在默认的系统时钟,2M / 1000 = 2000 ,所以模寄存器的值0x07d0。大家是别的主频的
    话,根据想要定时的周期,对应的调相关系数即可。有库函数用起来真的很简单。我再上传一个风驰大哥的教程。

    有了定时器的中断,必有中段函数,库模板已在库函数 stm8s_it.c中写好了
    INTERRUPT_HANDLER(TIM2_UPD_OVF_BRK_IRQHandler, 13)  //定时器2溢出中断
    {
       /*  用户函数*/
       TIM2_ClearITPendingBit(TIM2_IT_UPDATE);          //清除定时器2溢出中断
    }


    10-TIM1(定时).pdf










    数码管驱动

    数码管驱动分为动态驱动和静态驱动。这里只讲我的动态驱动的设计方案供大家参考
    我以前上学时老师教的动态驱动是这样的。
    void main(void)
    {
        while(1)
        {
            display_ONE();     //第一位数码管点亮
            delay_MS(10);     //延时个10ms
            display_TWO();     //第一位数码管点亮
            delay_MS(10);
            display_THR ();     //第一位数码管点亮
            delay_MS(10);
        }
    }
      这样的写法只适用学习如何动态显示数码管,他有两个不足的地方,一个是延时函数浪费了很多处时器时间,另一个是如果这个循环中再加上别的任务,随着工程量的加大,数码管就会越来越暗,有时候甚至不亮了。那么怎么办呢,那就得要基于动态显示的原理进行改进了。在上一段中,介绍了定时器,我分享下我的方法。我是把 这段程序放在中断中。
    INTERRUPT_HANDLER(TIM2_UPD_OVF_BRK_IRQHandler, 13)
    {
      switch(Dispay_Index)                    
      {
          case 0: LED4_Disable();Dispay_Index = 1;LED_Data=LED_Buff[4];LED0_Enable();break;       //LED指示灯
          case 1: LED0_Disable();Dispay_Index = 2;LED_Data=LED_Buff[0];LED1_Enable();break;       //第一位数码
          case 2: LED1_Disable();Dispay_Index = 3;LED_Data=LED_Buff[1];LED2_Enable();break;       //第二位数码
          case 3: LED2_Disable();Dispay_Index = 4;LED_Data=LED_Buff[2];LED3_Enable();break;       //第三位数码
          case 4: LED3_Disable();Dispay_Index = 5;LED_Data=LED_Buff[3];LED4_Enable();break;       //第四位数码
          default  : LED4_Disable();Dispay_Index = 0;KEY_Scan();break;    //扫描按键
      }
    }
    我的这段程序是这样的一个功能,每次进中断,更换显示一位数码管。在中断中可使数码管的显示与工程的主任务独立起来。不管其它地方如何变化,
    数码管的显示总会是稳定的。Dispay_Index 它是一个全局变量。如果临时变量的话,在退出中断时它的值就消失了。最后default建议大家一定要使
    用,因为它使得这个显示程序具有程序跑飞时的自我修正能力。由于我的LED和数码管是共用段码口的。所以我把LED就当作一位数码管来看待了。
    我的按键也是共用端口的,所以我也是把它当作一位数码管来看待的,只不过数码管是输出,它是输入而已。下一段我和大家分享一下我的按键驱动
    方法
      
      




    STM8S按键驱动


         按键分为独立按键和矩阵按键,矩阵按要比独立按键省I/O口,但是驱动程序要复杂。这两者各种有利有弊,那么有没有两者兼得的方法呢。如果的你的工程中有段式LED的话,恭喜你中奖了,看看我的方法吧。
        从我的测线板的原理图中可以看出,我在不增加I/O的情况下,让我的测线板多上了8个独立按键。那么如何驱动这8个独立按键呢。以前学
    的都是,先判断到有按键按下,再等10ms,如果按键还是按下的,则置下按键按下标志。那么问题来了,10ms的延时(不符合节约的原则),还有
    如果我的按是长按的怎么处理呢。我分享下我的方法。我也是在中断中处理的。
        我会为什么时候执行显示,什么时候处理按键检测 排个次序。有点类似操作系统中的分时复用。现在把执行按检测的部分独立起来看。
        每次执行按键检测的时候,我会先判断8个按键的状态,看看有没有被按下,如果没有,则不用理会。如果有,则记下一标记,下一次时中断,还
    有按下,那好了,程序就认定有按键按下了,接下来的连续几次进中断,还是有按下,则认定它为长按了。我附上我的程序。


    KEYStatusDef KEYStatus;     //按键的状态 分为三种: 没有按下;   已经按下了,等待下一个中断确认; 等待按键松开,或确认为长按
    KEYValueDef  KEY_Value;
    FunctionStatus KEY_Flag;
    static Uint8  KEY_Temp1;
    static Uint8  KEY_Temp2;

    static void KEY_PortScan(void)   // 从没有按键按下到按键的确认
    {
      KEY_Temp1 = KEY_Data;
      if(KEY_Temp1 != 0xff)
      {   
        KEYStatus = KEYStatus_Ok;
      }
    }

    static void KEY_PortOk(void)      //从确认按键下到等待按键的松开
    {
      KEY_Temp2 = KEY_Data;
      if((KEY_Temp2 == KEY_Temp1)&&(KEY_Temp2 != 0xff))   //再次判断按键,如果值和上次相同,则认定有按键按下
      {
        KEY_Value = (KEYValueDef)KEY_Temp2;         //保存按键值
        KEYStatus = KEYStatus_Pro;
        KEY_Flag = L_TRUE;                                      //置按键按下标志位
      }else KEYStatus = KEYStatus_Scan;   
    }

    static void KEY_PortPro(void)      //判断按键的松开,去检测下一个按键的按下
    {
      KEY_Temp1 = KEY_Data;
      if(KEY_Temp1 == 0xff) KEYStatus = KEYStatus_Scan;
      else /*判断按键 长按*/
    }

    static void KEY_Scan(void)
    {
      KEY_Input();                 // 置I/O为输入端口,用来检测按键输入功能
    //在主频比较大时,内核的处理速度大于I/O的处理速度,因为I/O最大输出速度只有10M,输入更低。STM8S最高主频有24M,这里加空操作,数量按实//际测试而定,我为工程的稳定性,很保留的加了10个nop();,5个也可以了。
    #if UserSystemClock > 6      
      nop(),nop(),nop(),nop(),nop(),nop(),nop(),nop(),nop(),nop();  
    #endif
      if(KEYStatus == KEYStatus_Pro) KEY_PortPro();        //有按键按下,等待按键松开或按键长按认定
      else if(KEYStatus == KEYStatus_Ok) KEY_PortOk();   //确认按键按下
      else KEY_PortScan();                                                 //扫描有没有按键按下,  这一个放在最后,用 else,也是为了让程序具有自动修复能力
      KEY_Output();              //置I/O为输出端口,用于显示功能
    }

    void KEY_Varible_Init(void)     //初始化按键相关变量的初始值.
    {
      KEYStatus = KEYStatus_Scan;
      KEY_Value = KEYVal_NO;
      KEY_Temp1 = 0xff;
      KEY_Temp2 = 0xff;
      KEY_Flag = L_FASE;
    }


    上面的介绍只是代码部分,硬件部分有个地方大家要注意,就是那个按键公共端上面接了一个电阻R10。它取值很重要,为了防止在按键按下时,数码管对应的段不亮。综合下面的两点,我的板子上R10实际取的是2K;

    1  参考STM8SR207RB数据手册,STM8认定0.3VDD为低电平,保守一点,最好不要超过0.15倍VDD。而按的上接电阻是33K,其实有点大了,
        我实际焊板测试后,选取的是22K,因为这直接影响了前面判断按键状态的准确性,还有一点大家不要忽视了,芯片内部还有个上接电阻,
       根据数据手册 上接电阻为30~80K.
    2 数码管点亮它有一个压降(大家不要认数码管也是0.7V),大多数码管是2~3V的样了。所以数码管与单片机连接处加一个限流电阻,这个电
       阻是多少?
          a,数码管点亮2ma足够了。(5 - 3)/ 2 = 1K  ,尽可能的减小这个电流,单片机驱动能力是有限的
          b , I/O输出的5V分在限流电阻和R10上,保证R10的电压大于3V。



    端口电气特性




    这一节介绍下如何基于库函数的头文件让STM8S支持位操作




        在使用51单片机中,我们可以很方便的定义位  sbit  LED_0 = P0^1;
       但STM8S库和IAR并不支持这样的操作,这给我们在写应用代码时带来了很多不便。那我们只能对面STM8S的I/O寄存器进行重新封装了。
       在正式写程序时,我们要了解结构体在内存分配时,内存是连续不断的一片。 结构体和联合体部分不太理解的同学大家网找找。
       先看库是如何封装I/O寄存器的。
       typedef struct GPIO_struct     //定义I/O结构体类型
    {
      __IO uint8_t ODR; //!< Output Data Register
      __IO uint8_t IDR; //!< Input Data Register
      __IO uint8_t DDR; //!< Data Direction Register
      __IO uint8_t CR1; //!< Configuration Register 1
      __IO uint8_t CR2; //!< Configuration Register 2
    }
    GPIO_TypeDef;  

    #define GPIOA ((GPIO_TypeDef *) GPIOA_BaseAddress)   //强制定义端口名

          这样的话,我们想往 GPIOA上送数据,只要这样即可:
          GPIO->ODR = 0x01;        //即可轻松的为 GPIOA端口赋值了

    我们要如何封装呢。这是我现在用的。
    typedef struct GPIOBIT_struct    //重新定义端口  因为一般只要用到数据输入和输出即可,我只定义了 ODR 和 IDR
    {
    union
    {
       __IO uint8_t    All;
       struct
       {
       __IO uint8_t B0:1;
       __IO uint8_t B1:1;
       __IO uint8_t B2:1;
       __IO uint8_t B3:1;
       __IO uint8_t B4:1;
       __IO uint8_t B5:1;
       __IO uint8_t B6:1;
       __IO uint8_t B7:1;
      }Bits;
    }ODR,IDR;
    }GPIOBIT_TypeDef;

    #define GPIOANEW (*((GPIOBIT_TypeDef *) GPIOA_BaseAddress))

        这样将GPIOA重新命名为 GPIOANEW  现在往GPIOA口输出数据就可以样写了
        GPIOANEW->ODR.All = 0x01;
        单独往第1位写如何写呢? 如下即可。
       GPIOANEW->ODR.Bits.B0 = 1  

       这样写是不是太麻烦呢,我们再封装它
       #define  GPIOA_0  GPIOANEW->ODR.Bits.B1
        GPIOA_0 = 1;

    关于它的位操作这么多也差不多够用了,其它大家自己多思考了

      




    接下来就是介绍如何进行测线了。




    在测线程序设计之前,还是老样子,先想好这个用什么方法去测。
    在大批量生产排线的时候,一般会出现如下三种问题
    1.  线断了     2. 线交叉了     3.可能存在接触不良的情况
    如果用人眼去识别哪些线不好,哪些是好的。几根好办,几千条线呢,几万条怎么办呢。  只能借助自动化设备了。

    我呢提供一个我的思路。我还是放在中断当中去做。
    第1次进中断,我给第1根线送一个低电平,再在线的另一端去检测它,将这个值保存在变量的第1位中,再将第1个端口复位为高电平
    第2次进中断,我给第2根线送一个低电平,再在线的另一端去检测它,将这个值保存在变量的第2位中,再将第2个端口复位为高电平
    ...
    ...
    第12次进中断,我给第12根线送一个低电平,再在线的另一端去检测它,将这个值保存在变量的第12位中,再将第12个端口复位为高电平
    测完了12根线后。我判断这12根的状态,并保留下来。作一次测线计数。
    我们知道是线插上插座和拔下插座的过程中,这个状态是不稳定的。为了避免这个情况的误判, 我每次在测完12根线的循环之后,都记下它的
    状态,直到10次连续测量的状态都是一样的,才最终认定这根线是好还是不好。
    1.  对于好的线,在数码管上面显示一个 PASS  表示通过
    2.  那么对于不好的呢,找出是哪一根线不好,并把它在数码管上显示出来,让检测人员贴上标签,便于产线上工作人员维修
         如何算快速算这个线是哪一根呢?方法有很多种,
         我用的是杳表法。把UCOSII当中 找最高优先级的表给复制过来就可以了。

    是不是这样就算完了呢,为了使我们做出来的东西更像一个产品,我们还要给它润色。
      1. 我还会让产品计下测量多少个排线,产品的合格率是多少?
      2. 将最近10次的产品测量数据进行对比,看看产品的生产效率和合格的率情况,  便于提高生产 (STM8S有内部EEPROM,这些数必须保存在其中)
      3. 根据其它产品的需要,我测的线肯定能只是12根的。 只要不超过12根,我们可以通过这个菜单去设定的
      4. 可以通串口将这些数据上传到电脑上,结合上位机软件,将它们制表格


    如何去写这个菜单的结构,其实也有很多东西,大家可以在别处杳查。在8位机写一个很大的菜单,而且要有高的处理速度,我用是的结构体去做的,
    也是在网上的一位大哥的贴子上学的,可如今找不到连接了,它可以让一个10 x10 的菜单执行速度 和 1X 1速度一样快。

    这个测线板本来是想写成教大家入门STM8S的,我不常写这一类文档。由于工作上比较忙,写着写着就变了。我更多的是写出了我平常工作中总结
    出来的比较好的程序设计思想。我把我的程序也上传过上来。

    个人写文档能力差,希望能有写文档能力强的朋友指导指导。俗话说: 会写画板子,会写程序的叫技术员; 会写报告、会做计划的是经理;  会做策划,会做方案的是老板。

    祝我们这些一心想学想做技术的朋友们早是成为老板!!!!




    如果家能看我的贴子做出了这个测线板,那么STM8S的应用也就没有什么问题了。我在上传一基于UCOSII2.5的测线板的程序,让大家学一学UCOSII 的使用 和如何把UCOSII 移植到STM8S上面,移植我参考的也是风驰大哥的教程,他移植的UCOSII 2.9 ,我自己在学完教程后移植的是UCOSII 2.52版的。我讲一点个人对写程序感想吧。写程序最重要的程序的结构,写程序的代码风格。其实学会用一个单片机并不难,像STM8S买一块开发板,对着入门教程很快就会了,我入门大概花了两周的时间吧。(这里我真心感谢风驰大哥,他把他的教程免费共享出来,在我心中他和STM32的原子哥都非常值得我们去尊敬,他们把他们的东西免费共享给了很多利益不相干的人,包括他们的竟争对手,这不是一般人能做到的)
    游客,如果您要查看本帖隐藏内容请回复






    回复

    使用道具 举报

  • TA的每日心情
    奋斗
    2023-9-15 00:01
  • 签到天数: 1371 天

    连续签到: 3 天

    [LV.10]以坛为家III

    发表于 2020-6-19 09:39:10 | 显示全部楼层
    有详细的东西下载吗?
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    昨天 08:10
  • 签到天数: 1542 天

    连续签到: 333 天

    [LV.Master]伴坛终老

    发表于 2022-9-28 07:35:03 | 显示全部楼层
    谢谢楼主分享 学习一下
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

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

    手机版|小黑屋|与非网

    GMT+8, 2024-5-18 06:18 , Processed in 0.141676 second(s), 22 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.