登录|立即注册|使用QQ帐号登录
论坛 > 51单片机
发帖|
看8752|回14|收藏
楼主 ID:249059 只看他
2017-11-13 20:18
说明: 本例用PIC单片机控制带感应器的直流无刷电机,通过调节RA0端口的可变电阻器可实现电机调速控制.由于当前版本PROTEUS不支持换向功能,连接RA1端口的SW1尚不能控制无刷电机的运行方向.

仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
0.png 0.png 0.png


单片机源程序如下:

代码:


  1. //-----------------------------------------------------------------
  2. //  名称: 带位置感应器的直流无刷电机PMW控制仿真
  3. //-----------------------------------------------------------------
  4. //  说明: 本例用PIC单片机控制带感应器的直流无刷电机,通过调节RA0端口的
  5. //       可变电阻器可实现电机调速控制.
  6. //       由于当前版本PROTEUS不支持换向功能,连接RA1端口的SW1尚不能控制
  7. //       无刷电机的运行方向.
  8. //  
  9. //-----------------------------------------------------------------
  10. #include <xc.h>
  11. #define INT8U  unsigned char
  12. #define INT16U unsigned int
  13. #define _XTAL_FREQ 20000000UL           //20MHz
  14. #define  BLDC_StopMask       0B11010101 //关闭电机的掩码(高边设为全0)
  15. #define  BLDC_DrivePort      PORTC      //无刷直流电机驱动方向控制端口(6位)
  16. #define  BLDC_DrivePortTris  TRISC      //无刷直流电机驱动方向控制端口方向设置
  17. #define  BLDC_Direction      RA1        //无刷直流电机当前方向检测位
  18. #define  BLDC_SensorPORT     PORTE      //无刷直流电机感应器输入端口
  19. #define  BLDC_SensorTRIS     TRISE      //无刷直流电机感应器输入端口方向寄存器
  20. volatile INT8U ADC_Result;              //控制PWM的AN0通道A/D转换数据
  21. volatile INT8U DriveByte;               //电机驱动字节(低6位有效)
  22. //-----------------------------------------------------------------
  23. // 驱动表设置(更详细说明可参阅本书相关章节)
  24. //-----------------------------------------------------------------
  25. //1.6个驱动器共为3对,每2个为一对
  26. //2.每一对驱动线由一个高边和一个低边构成
  27. //3.三个驱动器对应于三个电机绕组A,B,C
  28. //4.绕组 A 由RC[1..0]两位驱动,其中RC1是 A 绕组的高边
  29. //5.绕组 B 由RC[3..2]两位驱动,其中RC3是 B 绕组的高边
  30. //6.绕组 C 由RC[5..4]两位驱动,其中RC5是 C 绕组的高边
  31. //7.三个感应器位构成了驱动表的偏移地址,感应器位[0..2]分别对应于绕组A,B,C
  32. //正向驱动数据表,第1-6字节对应于相位6,4,5,2,1,3的驱动位,各字节中仅低6位有效
  33. //驱动表中第0,7两字节无效
  34. const INT8U FwdTable[] =
  35. {

  36. };
  37. //反向驱动数据表,第1-6字节对应于相位/6,/4,/5,/2,/1,/3的驱动位,0,7两字节无效
  38. //表中每个字节后6位中,相邻两位为一组,与上表的差别是每组中的两位颠倒
  39. const INT8U RevTable[] =
  40. {
  41. };
  42. //-----------------------------------------------------------------
  43. // 换向控制
  44. //-----------------------------------------------------------------
  45. void Get_Drive_Byte()
  46. {
  47.     //读取PORTE端口输入的感应器当前数据(三位)
  48.     INT8U CurrentSensor = PORTE & 0B00000111;
  49.     //根据RA1端口的方向位及当前位置感应器输出,从正向或反向驱动表中读取驱动字节
  50.     if (BLDC_Direction == 0)
  51.        DriveByte = FwdTable[CurrentSensor];
  52.     else
  53.        DriveByte = RevTable[CurrentSensor];
  54. }
  55. //-----------------------------------------------------------------
  56. // 初始化程序
  57. //-----------------------------------------------------------------
  58. void Initialize()
  59. {
  60.     Get_Drive_Byte();            //根据当前电机位置取得驱动字节
  61.     ADC_Result= 0x00;            //初始速度控制值为0
  62.     BLDC_DrivePort = 0x00;       //关闭BLDC驱动端口
  63.     BLDC_DrivePortTris = 0x00;   //BLDC驱动方向端口设为输出
  64.     BLDC_SensorTRIS = 0xFF;      //无刷直流电机感应器端口设为输入
  65.     TRISA  = 0B00000011;         //AN0为模拟量输入,RA1为电机方向控制
  66.     T0CS = 0;                    //TMR0时钟选择:内部时钟
  67.     PSA = 0;                     //前分频器分配给TMR0
  68.     PS2 = 1; PS1 = 1; PS0 = 1;   //256分频(OPTION低3位为111,4M,256us)
  69.     ADCON1 = 0B00001110;         //A/D转换结果左对齐,AN0为模拟端口,其余为数字端口
  70.     ADCON0 = 0B11000001;         //A/D时钟源:RC,ADON置位,使能A/D模块
  71.     GO_nDONE = 1;                //启动ADC
  72. }
  73. //-----------------------------------------------------------------
  74. // 读取A/D转换结果的高8位
  75. //-----------------------------------------------------------------
  76. void ReadADC()
  77. {
  78.     //如果模/数转换已经就绪则读取速度控制值并重新启ADC,以便读取一次ADC结果
  79.     if (GO_nDONE) return;
  80.     ADC_Result = ADRESH;         //读取A/D结果的高8位
  81.     GO_nDONE = 1;                //重启A/D模块
  82. }        
  83. //-----------------------------------------------------------------
  84. // 主程序
  85. //-----------------------------------------------------------------
  86. void main()
  87. {
  88.     Initialize();
  89.     while (1)
  90.     {
  91.        ReadADC();//从模/数转换端口读取速度控制值
  92.        //如果A/D转换值为最大值则电机全速运行,否则调节PWM
  93.        //占空比 = ADC_Result / 255
  94.        if (ADC_Result != 0xFF)
  95.        {
  96.           if (TMR0 + ADC_Result <= 0xFF) DriveByte &= BLDC_StopMask;
  97.        }
  98.        //发送电机驱动字节(6位),驱动电机运行
  99.        BLDC_DrivePort = DriveByte;
  100.        //根据电机位置感应器输出的当前位置取得新的驱动字节
  101.        Get_Drive_Byte();
  102. ……………………

  103. …………限于本文篇幅 余下代码请从51黑下载附件…………

所有资料51hei提供下载:
带位置感应器的直流无刷电机PMW控制仿真.rar (64.17 KB)
(下载次数: 228, 2017-11-13 20:17 上传)

下载积分: 黑币 -5




沙发 ID:61135 只看他
2017-11-14 09:53
程序不全
板凳 ID:286498 只看他
2018-3-1 09:20
谢谢分享。。。。
地板 ID:286498 只看他
2018-3-1 09:20
谢谢分享。。。。。
5# ID:240034 只看他
2018-3-2 17:03
楼主用的PROTEUS是哪个版本
6# ID:249545 只看他
2018-4-15 16:40
感谢老师给学生分享,问下老师,程序是完整的吗?
7# ID:261010 只看他
2018-5-7 22:16
感谢!!!!!!!!!!!!!!!!!
8# ID:333778 只看他
2018-5-28 12:26
驱动表怎么没有呀,能发一下吗
9# ID:342906 只看他
2018-6-1 15:18
谢谢分享!!
10# ID:407471 只看他
2018-10-10 15:13
学习一下,程序齐全吗?
11# ID:395522 只看他
2019-1-31 16:21
正反转的编码如下,刚好我也在学马达控制,分享给各位,感谢楼主的分享
const INT8U FwdTable[] = {0, 50, 11, 56, 44, 14, 35, 0
//0x00, 0x32, 0x0b, 0x38, 0x2c, 0x0e, 0x23, 0x00};

const INT8U RevTable[] = {0, 35, 14, 44, 56, 11, 50, 0
//0x00, 0x23, 0x0e, 0x2c, 0x38, 0x0b, 0x32, 0x00};
12# ID:518540 只看他
2019-4-22 13:54
谢谢分享!!!
13# ID:518540 只看他
2019-4-22 14:23
谢谢分享!!!
14# ID:443710 只看他
2020-1-4 23:31
太牛逼了
15# ID:563624 只看他
2020-2-22 10:38
谢谢分享,好好学习一下

51黑电子论坛

Powered by Discuz! X3.1

首页|标准版|触屏版|电脑版