[USB芯片] 【CH32X035评估板测评】+ 高级定时器TIM2测量霍尔PCB相位差

[复制链接]
 楼主| 袁胜富 发表于 2023-10-10 23:50 | 显示全部楼层 |阅读模式
本帖最后由 袁胜富 于 2023-10-12 09:05 编辑

#申请原创#
一、概述


CH32X035拥有两个高级定时器,TIM1和TIM2,每个定时器拥有四个输入通道,可以输出PWM也可以捕获PWM,平时也可以作为通用定时器使用。
在无刷有霍尔感应的电机,每一个电机需要一个霍尔板,霍尔板上有三颗霍尔元件,通用感应磁场位置进行编码,从而进行六步换相。在生产霍尔板时,需要对其进行良品测试,一般治具下面放个旋转电机,电机轴上放一个磁铁,转动电机模拟磁场变化,在盘上开辟可以完全同心的位置固定霍尔PCB板,当电机转动磁场变化产生霍尔信号,捕获霍尔信号的两两之间的相位差可以判定霍尔PCB的好坏。
此篇评测的是利用CH32X035的TIM2高级定时器外设捕获霍尔的三个信号,计算相位差,从而知道霍尔板的好坏。有兴趣或者有需要完整方案的人士可以联系我。
于是乎为了和大家分享,我出了这个文章。


二、原理分析和硬件连接

原理分析
824b58ec360e1c1ac9af209ec40c0e8d
图1如上图1
所示U1、U2和U3都是霍尔元件,一般公司生产需要测量硬件的好坏,在制作测试治具时一般需要使用定时器的输入捕获功能。
9803ea66ed9b52414e22014b64f3c952
图2
记H1的上升沿时刻为T1,记H2的上升沿时刻为T2,记H3的上升沿时刻为T3,周期为T。
H1和H2两个霍尔之间的相位差计算公式如下:
h1h2相位差计算.bmp
H2和H3两个霍尔之间的相位差计算公式如下:
h2h3相位差计算.bmp
硬件连接
霍尔板开发板
Hall1------>PA0
Hall2------>PA1
Hall3------>PA2
VCC------->VCC
GND------->GND


三、代码


HALL.H代码:
  1. #ifndef __HALL_H
  2. #define __HALL_H

  3. #include "debug.h"
  4. #include "String.h"
  5. #include "Stdlib.h"
  6. #include "Stdio.h"
  7. #include "Stdarg.h"
  8. #include "ctype.h"

  9. typedef struct
  10. {
  11.     float        Current_H1_H2_Phase_Diff;//H1和H2的相位差的当前测量值
  12.     float        LowerLimit_H1_H2_Phase_Diff;//H1和H2的相位差的下限值
  13.     float        UpperLimit_H1_H2_Phase_Diff;//H1和H2的相位差的上限值

  14.     float        Current_H2_H3_Phase_Diff;//H2和H3的相位差的当前测量值
  15.     float        LowerLimit_H2_H3_Phase_Diff;//H2和H3的相位差的下限值
  16.     float        UpperLimit_H2_H3_Phase_Diff;//H2和H3的相位差的上限值

  17.     float        Current_NTC_ADC_Value;//敏电阻电压当前测量值
  18.     float        LowerLimit_NTC_ADC_Value;//热敏电阻电压下限值
  19.     float        UpperLimit_NTC_ADC_Value;//热敏电阻电压上限值

  20.     float        Motor_DIR;//电机的转向设置---》1正转----》0反转

  21.     float        Hall_Board_Relay_Time;
  22. }Hall_DATA_TYPEDEF;

  23. extern Hall_DATA_TYPEDEF HALL_Capture_Data;
  24. extern volatile int HFlag;
  25. extern volatile int H1_Value;
  26. extern volatile int H2_Value;
  27. extern volatile int H3_Value;

  28. void  Hall_Singal_Captrue(void);
  29. #endif


Hall.c代码
  1. #include "Hall.h"

  2. Hall_DATA_TYPEDEF HALL_Capture_Data ={0,0,0,0,0,0,0,0,0,0,0};
  3. volatile int Over_flower=0;
  4. volatile int H1_Value=0;
  5. volatile int H2_Value=0;
  6. volatile int H3_Value=0;
  7. volatile int HFlag=0;
  8. volatile int temp=0;
  9. volatile int  f1=0,f2=0,f3=1;


  10. void TIM2_CC_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
  11. void TIM2_UP_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));

  12. void  Hall_Singal_Captrue(void)
  13. {
  14.     GPIO_InitTypeDef GPIO_InitStructure={0};
  15.     TIM_ICInitTypeDef TIM_ICInitStructure={0};
  16.     TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure={0};
  17.     NVIC_InitTypeDef NVIC_InitStructure={0};

  18.     RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE );
  19.     RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM2, ENABLE );

  20.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2;
  21.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
  22.     GPIO_Init( GPIOA, &GPIO_InitStructure);

  23.     TIM_TimeBaseInitStructure.TIM_Period = 0xFFFF - 1;
  24.     TIM_TimeBaseInitStructure.TIM_Prescaler = 48-1;
  25.     TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
  26.     TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
  27.     TIM_TimeBaseInitStructure.TIM_RepetitionCounter =  0x00;
  28.     TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);


  29.     TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
  30.     TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
  31.     TIM_ICInitStructure.TIM_ICFilter = 0x00;
  32.     TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
  33.     TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
  34.     TIM_ICInit(TIM2, &TIM_ICInitStructure );

  35.     TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
  36.     TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
  37.     TIM_ICInitStructure.TIM_ICFilter = 0x00;
  38.     TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
  39.     TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
  40.     TIM_ICInit(TIM2, &TIM_ICInitStructure );

  41.     TIM_ICInitStructure.TIM_Channel = TIM_Channel_3;
  42.     TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
  43.     TIM_ICInitStructure.TIM_ICFilter = 0x00;
  44.     TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
  45.     TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
  46.     TIM_ICInit(TIM2, &TIM_ICInitStructure );

  47.     NVIC_InitStructure.NVIC_IRQChannel = TIM2_UP_IRQn;
  48.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  49.     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  50.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  51.     NVIC_Init(&NVIC_InitStructure);

  52.     NVIC_InitStructure.NVIC_IRQChannel = TIM2_CC_IRQn;
  53.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  54.     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  55.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  56.     NVIC_Init(&NVIC_InitStructure);

  57.     TIM_ITConfig( TIM2, TIM_IT_CC1 | TIM_IT_CC2 | TIM_IT_CC3 | TIM_IT_Update, ENABLE );
  58.     TIM_ClearITPendingBit(TIM2, TIM_IT_CC1 | TIM_IT_CC2 | TIM_IT_CC3 | TIM_IT_Update);

  59.     TIM_Cmd( TIM2, ENABLE );
  60. }


  61. void TIM2_UP_IRQHandler(void)
  62. {
  63.     if(TIM_GetFlagStatus(TIM2, TIM_FLAG_Update) != RESET)
  64.     {
  65.         if(TIM_GetITStatus(TIM2,TIM_IT_Update) != RESET)
  66.         {
  67.             Over_flower++;
  68.         }
  69.     }
  70.     TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
  71. }

  72. void TIM2_CC_IRQHandler(void)
  73. {
  74.     if(TIM_GetFlagStatus(TIM2, TIM_FLAG_CC1)!= RESET)
  75.     {
  76.         if(TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET)
  77.         {
  78.             if(f3 == 1)
  79.             {
  80.                 H1_Value = (TIM2->CNT + 1) + (Over_flower * 65536);
  81.                 HFlag = 1;
  82.                 TIM_SetCounter(TIM2, 0);
  83.                 Over_flower = 0;
  84.                 f3 = 0;
  85.                 f1 = 1;
  86.             }
  87.         }
  88.     }

  89.     if(TIM_GetFlagStatus(TIM2, TIM_FLAG_CC2)!= RESET)
  90.     {
  91.         if(TIM_GetITStatus(TIM2, TIM_IT_CC2) != RESET)
  92.         {
  93.             if(f1 == 1)
  94.             {
  95.                 H2_Value = (TIM2->CNT + 1) + (Over_flower * 65536);
  96.                 f2 = 1;
  97.                 f1= 0 ;
  98.             }
  99.         }
  100.     }
  101.     if(TIM_GetFlagStatus(TIM2, TIM_FLAG_CC3)!= RESET)
  102.     {
  103.         if(TIM_GetITStatus(TIM2, TIM_IT_CC3) != RESET)
  104.         {
  105.             if(f2 == 1)
  106.             {
  107.                 H3_Value = (TIM2->CNT + 1) + (Over_flower * 65536);
  108.                 f2 = 0;
  109.                 f3 = 1;
  110.             }
  111.         }
  112.     }

  113.     TIM_ClearITPendingBit(TIM2, TIM_IT_CC1 | TIM_IT_CC2 | TIM_IT_CC3);
  114. }

Main.c代码
  1. #include <stdio.h>
  2. #include "debug.h"
  3. #include "Hall.h"

  4. u8 H1=0,H2=0,H3=0;
  5. float UV_Temp=0.0;
  6. float VW_Temp=0.0;
  7. int NTC_Temp = 0;
  8. float ntc_Temp=0.0;
  9. float UV=0.0;
  10. float VW=0.0;


  11. /*********************************************************************
  12. * @fn      main
  13. *
  14. * [url=home.php?mod=space&uid=247401]@brief[/url]   Main program.
  15. *
  16. * [url=home.php?mod=space&uid=266161]@return[/url]  none
  17. */
  18. int main(void)
  19. {
  20.     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  21.     SystemCoreClockUpdate();
  22.     Delay_Init();
  23.     USART_Printf_Init(115200);
  24.     Hall_Singal_Captrue();//波形捕获定时器初始化
  25.     while(1)
  26.     {
  27.         if(HFlag == 1)
  28.         {
  29.             HFlag= 0;
  30.             HALL_Capture_Data.Current_H1_H2_Phase_Diff = ((float)H2_Value/(float)H1_Value)*360.0;
  31.             HALL_Capture_Data.Current_H2_H3_Phase_Diff = ((float)(H3_Value -H2_Value)/(float)H1_Value)*360.0;

  32.             printf("UV_Value=%f\r\n",HALL_Capture_Data.Current_H1_H2_Phase_Diff);
  33.             printf("VW_Value=%f\r\n\r\n",HALL_Capture_Data.Current_H1_H2_Phase_Diff);

  34.         }
  35.     }
  36. }




四、展示



4932126c77a4772dd91d73fd8a5d2c4f
工程源码在附件。

CH32X035C8T6_HallAngle.zip

545.06 KB, 下载次数: 6

tpgf 发表于 2024-1-18 18:42 | 显示全部楼层
我能理解相位差,但是不能理解什么叫做pcb相位差
wakayi 发表于 2024-1-18 19:19 | 显示全部楼层
只有高级定时器才具有捕获比较的功能吧

评论

其他不清楚,CH32、STM32的高级定时器和通用定时器都具有输入捕获和输出比较功能  发表于 2024-1-19 13:58
paotangsan 发表于 2024-1-19 08:08 | 显示全部楼层
如果波形不是方波而是正弦波的话 这个相位差就不那么好测了吧
renzheshengui 发表于 2024-1-19 08:52 | 显示全部楼层
这种相位差使用普通的定时器可以进行测量吗
wowu 发表于 2024-1-19 09:29 | 显示全部楼层
这种采集方式还需要对外部电路进行防抖设计吗
xiaoqizi 发表于 2024-1-19 10:11 | 显示全部楼层
这个和能感应到的磁通量有关系吗
 楼主| 袁胜富 发表于 2024-1-21 13:46 | 显示全部楼层
xiaoqizi 发表于 2024-1-19 10:11
这个和能感应到的磁通量有关系吗


 楼主| 袁胜富 发表于 2024-1-21 13:47 | 显示全部楼层
wowu 发表于 2024-1-19 09:29
这种采集方式还需要对外部电路进行防抖设计吗

看情况
 楼主| 袁胜富 发表于 2024-1-21 13:47 | 显示全部楼层
renzheshengui 发表于 2024-1-19 08:52
这种相位差使用普通的定时器可以进行测量吗

带捕获功能定时器就可以
您需要登录后才可以回帖 登录 | 注册

本版积分规则

32

主题

163

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部