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

基于一块测线板,让你从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扩展软件包
关注我们
微信公众号二维码 微信公众号
手机版二维码 手机版