你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

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

[复制链接]
w453509596 发布时间:2015-1-8 21:14
阅读主题, 点击返回1楼
收藏 5 评论44 发布时间:2015-1-8 21:14
44个回答
w453509596 回答时间:2015-1-8 21:59:54

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

本帖最后由 w453509596 于 2015-1-9 11:57 编辑

    在使用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;

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

  



w453509596 回答时间:2015-1-8 22:00:11

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

本帖最后由 w453509596 于 2015-1-9 12:47 编辑

在测线程序设计之前,还是老样子,先想好这个用什么方法去测。
在大批量生产排线的时候,一般会出现如下三种问题
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的,我不常写这一类文档。由于工作上比较忙,写着写着就变了。我更多的是写出了我平常工作中总结
出来的比较好的程序设计思想。我把我的程序也上传过上来。

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

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




测线板程序.rar

下载

413.18 KB, 下载次数: 55

测线板程序

adersonl 回答时间:2015-1-8 22:08:02
那玩意儿就十块多钱一个有必要么。
w453509596 回答时间:2015-1-9 13:00:31

基于UCOSII 的测线板程序

本帖最后由 w453509596 于 2015-1-9 13:07 编辑

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

基于UCOSII的测线板.rar

下载

478.04 KB, 下载次数: 42

w453509596 回答时间:2015-1-9 13:11:55

关于STM8S看门狗

本帖最后由 w453509596 于 2015-1-9 13:14 编辑

关于STM8S的看门狗,有一点非常要注意,它这个和我正常写看门狗不太一样。它要先开启看门狗,然后才能对看门狗进行配置,这一点官方的参考手册上标的不太明确
STM8S的看门狗应该是这样的顺序

static void MCU_IWOG_Init(void)   //看门狗初始化,只允许写一次
{
  IWDG_Enable();                                //开看门狗
  IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable); //写允许
  IWDG_SetPrescaler(IWDG_Prescaler_256);        //256分频
  IWDG_SetReload(0xfe);                         //254的重载值
  IWDG_ReloadCounter();                         //刷新计数
}
w453509596 回答时间:2015-1-9 13:17:58

基于STM8S的外部I/O 中断 红外遥控解码

本帖最后由 w453509596 于 2015-1-11 10:48 编辑

基于STM8S的红外遥控功能。我给大家分享一段代码。由于是产品了,不上传全部程序了
FuncState InfraredWate_Flag;  //等待按键松开标志
Uint8 InfraredWate_Index;     //用于等待按键松开计时
FuncState InfraredRec_Flag;   //红外采集完成标志
Uint8 InfraredCode;           //红外接收代码
Uint8 InfraredCode_Index;     //红外接位计数
Uint8 InfraredBuffer_H;       //红外识别码接收缓存
Uint8 InfraredBuffer_L;       //红外接收代码缓存
Uint8 InfPeriod_Status;       //红外周期状态
Uint16 TimeCounterVal;        //计数器临时值
Uint8 ReciveIndex;            //红外接收计数

static void TimeCounter_Start(void)    //启动计数
{
    TIM2->CNTRH = 0;
    TIM2->CNTRL = 1;
    TIM2->CR1 |= 0x01;
}

void TimeCounter_Stop(void)    //停止计数
{
    TIM2->CR1 &= 0xfe;
}

static void InfraredRec_Bit(Uint8* BufferAddr)
{
   if((12000 < TimeCounterVal)&&(TimeCounterVal < 22000))    //0周期约为17000
   {
     *BufferAddr = (*BufferAddr) * 2;
   }
   else if((30000 < TimeCounterVal)&&(TimeCounterVal < 40000))  //1周期约为35000
   {
     *BufferAddr = ((*BufferAddr) * 2) + 1;
   }
   else ReciveIndex = 0;
}

void InfraredInterrupt_Process(void)
{
  if(InfraredWate_Flag != L_FASE)       //等待接收到按键松开的间隔符,才开始下次接收  每次中断4ms,10次约40ms
  {
    if(InfraredWate_Index <10) InfraredWate_Index ++;  
    else
    {
      InfraredWate_Flag = L_FASE;                                   //已等到间隔符,清标志位      
      TimeCounter_Stop();  
      InfPeriod_Status = InfPeriod_Start;
    }
  }
  else                            //防止计数中间产生的,错把间隔符当成正常位。还有一种是由于排除红外不工作时产生的干扰。
  {
    TimeCounter_Stop();
    InfPeriod_Status = InfPeriod_Start;
  }
}

void PeripheralInfrared_Receive(void)
{
  if(InfraredWate_Flag == L_FASE)                            //处于非等待间隔符状态,开始正常接收  
  {
    if(InfPeriod_Status == InfPeriod_Stop)                   //开始接收数据
    {
      disableInterrupts();
      TimeCounterVal  = ((uint16_t)TIM2->CNTRH << 8);
      TimeCounterVal |= (uint16_t)(TIM2->CNTRL);
      TimeCounter_Start();
      enableInterrupts();                                //存在一些硬件上的互锁机制,为了使得数据更准确,这里关掉中断,防止其它干扰
      
      ReciveIndex ++;
      if(ReciveIndex <= 8)  InfraredRec_Bit(&InfraredBuffer_H); //前8位数据
      else  InfraredRec_Bit(&InfraredBuffer_L);                 //后8位数据               
      if(ReciveIndex >= 16)
      {
        InfPeriod_Status = InfPeriod_Start;
        if(InfraredBuffer_H == InfraredUser_Code)   //如果识别码正确
        {
          InfraredWate_Flag = L_TRUE;               //已接收到功能码,等待间隔符
          InfraredWate_Index = 0;
          InfraredRec_Flag = L_TRUE;               //
          InfraredCode = InfraredBuffer_L;         // 将数据送入缓存区  
        }
      }
    }
    else                                      //如果接收到了启始符,置标志位,开始接收数据
    {
      TimeCounter_Start();
      InfPeriod_Status = InfPeriod_Stop;
      ReciveIndex = 0;
    }

  }
  else InfraredWate_Index = 0;                //在等待按键松开,理论上讲,是不允许再接收重复红外信号的
}https://www.stmcu.org.cn/module/foru ... &pid=2049512&page=1

void Infrared_InitVar(void)
{
  InfPeriod_Status = InfPeriod_Start;
  TimeCounterVal = 0;
  ReciveIndex = 0;
  InfraredBuffer_H = 0;
  InfraredBuffer_L = 0;
  InfraredCode = 0;
  InfraredCode_Index = 0;
  InfraredRec_Flag = L_FASE;
  InfraredWate_Flag = L_FASE;
  InfraredWate_Index = 0;
}


在这个红外编码中由16位组成一串字帧。0 由 0.26ms的低电平和0.8ms的高电平表示, 1由 0.26ms的低电平和1.8的高电平表示。
两者的周期相差一倍,我把红外信号由红外接收头HS3818接收后送到STM8S的外部中断I/O上面,我是根据数据周期来判断是0
还是1的。
w453509596 回答时间:2015-1-10 16:34:01
我感觉我分享的东西还是可以的吧,怎么就没什么人看呢
hfei1980 回答时间:2015-1-13 22:09:03
谢谢,刚转入STM8,请多指点。。
w453509596 回答时间:2015-1-13 22:46:15
hfei1980 发表于 2015-1-13 22:09
谢谢,刚转入STM8,请多指点。。

STM8S还是挺简单的,好好学,专心学习,天天学两周应该就可以了
mlxy123xy 回答时间:2015-1-14 09:59:43
很详细,可以作为教程。。。

所属标签

STM32团队

意法半导体微控制器和微处理器拥有广泛的产品线,包含低成本的8位单片机和基于ARM® Cortex®-M0、M0+、M3、M4、M33、M7及A7内核并具备丰富外设选择的32位微控制器及微处理器


最新内容

相似分享

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版