找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 7746|回复: 14
收起左侧

带位置感应器的直流无刷电机PMW控制仿真和单片机源码

  [复制链接]
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, 下载次数: 226)

评分

参与人数 1黑币 +15 收起 理由
GUOXUAN + 15 感谢老师分享!

查看全部评分

回复

使用道具 举报

ID:61135 发表于 2017-11-14 09:53 | 显示全部楼层
程序不全
回复

使用道具 举报

ID:286498 发表于 2018-3-1 09:20 | 显示全部楼层
谢谢分享。。。。
回复

使用道具 举报

ID:286498 发表于 2018-3-1 09:20 | 显示全部楼层
谢谢分享。。。。。
回复

使用道具 举报

ID:240034 发表于 2018-3-2 17:03 | 显示全部楼层
楼主用的PROTEUS是哪个版本
回复

使用道具 举报

ID:249545 发表于 2018-4-15 16:40 | 显示全部楼层
感谢老师给学生分享,问下老师,程序是完整的吗?
回复

使用道具 举报

ID:261010 发表于 2018-5-7 22:16 | 显示全部楼层
感谢!!!!!!!!!!!!!!!!!
回复

使用道具 举报

ID:333778 发表于 2018-5-28 12:26 | 显示全部楼层
驱动表怎么没有呀,能发一下吗
回复

使用道具 举报

ID:342906 发表于 2018-6-1 15:18 | 显示全部楼层
谢谢分享!!
回复

使用道具 举报

ID:407471 发表于 2018-10-10 15:13 | 显示全部楼层
学习一下,程序齐全吗?
回复

使用道具 举报

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};
回复

使用道具 举报

ID:518540 发表于 2019-4-22 13:54 | 显示全部楼层
谢谢分享!!!
回复

使用道具 举报

ID:518540 发表于 2019-4-22 14:23 | 显示全部楼层
谢谢分享!!!
回复

使用道具 举报

ID:443710 发表于 2020-1-4 23:31 | 显示全部楼层
太牛逼了
回复

使用道具 举报

ID:563624 发表于 2020-2-22 10:38 | 显示全部楼层
谢谢分享,好好学习一下
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表