zoukankan      html  css  js  c++  java
  • F28379D烧写双核程序(在线&离线)

    @

    文章信息

    撰写日期 2018.12.20
    完稿日期 2018.12.20
    最近维护 2019.07.14
    本文作者 multimicro
    联系方式 multimicro@qq.com
    GitHub https://github.com/wifialan
    本文地址 https://www.cnblogs.com/multimicro/p/9997615.html

    开发环境

    环境说明 详细信息 备注信息
    操作系统 Win10_x64
    CCS版本 Code Composer Studio v8 官网地址
    controlSUITE controlSUITE for C2000 MCUs 官网地址
    F28335 硬汉F28335开发板(150MHz时钟频率)
    欧姆龙E6B2编码器 E6B2-CWZ6C 1000 P/R

    捕获模块简介

    F28335的Ecap模块捕获过程如下
    在这里插入图片描述

    该定时器是捕获模块专用定时器,在设定好捕获事件后,每捕获一个事件,对应的各级捕获寄存器就会把时间记录在捕获寄存器里面,通过这些时间信息即可计算出速度信息。
    Ecap模块中比较重要的寄存器

    • eCAP控制寄存器ECCTL1
      用于配置触发捕获事件的条件和对应的计数器(一共四级,详见程序注释)
    • eCAP控制寄存器ECCTL2
      用于配置eCAP的工作模式,包括进入中断的方式等
    • eCAP捕获寄存器eCAPx
      用于记录各级捕获事件发生时的时间
    • 其余寄存器在代码中查看其作用

    对与F2837xD,其配置捕获模块的程序和F28335的程序完全一样,唯一的不同就是配置Ecap输入引脚方式不同,F28335有固定的Ecap输入引脚,而F2837xD的捕获输入因为加入了Crossbar(X-BAR)机制,使得配置输入引脚其他C2000系列DSP更加灵活,可以使用任何一个GPIO口作为捕获输入,在TI官方的F2837xD文档Technical Reference Manual上面可以看到如下配置捕获引脚的说明(P1955):
    在这里插入图片描述
    F2837xD配置捕获输入的GPIO口的程序就两行:

    在这里插入图片描述

    若想进一步了解X-BAR,参考上面提到的文档P1151页。


    详细代码

    /*
     * ecap.c
     *
     *  Created on: 2018年12月14日
     *      Author: multimicro
     */
    
    
    #include "project.h"
    
    void InitECapture()
    {
        InitECapture1();
        InitECapture2();
        InitECapture3();
    }
    
    void InitECapture1()
    {
        ECap1Regs.ECEINT.all = 0x0000;             // Disable all capture interrupts
        ECap1Regs.ECCLR.all = 0xFFFF;              // Clear all CAP interrupt flags
        ECap1Regs.ECCTL1.bit.CAPLDEN = 0;          // Disable CAP1-CAP4 register loads
        ECap1Regs.ECCTL2.bit.TSCTRSTOP = 0;        // Make sure the counter is stopped
    
        // Configure peripheral registers
        ECap1Regs.ECCTL2.bit.CONT_ONESHT = 1;      // 单次模式
        ECap1Regs.ECCTL2.bit.STOP_WRAP = 3;        // Stop at 4 events
        ECap1Regs.ECCTL2.bit.SWSYNC = 1;            //同步所有的Ecap时钟
        //以下CAP1POL是配置捕获单元的极性
        /*
         *      ____      ____      ____
         *     |    |    |    |    |    |
         * ____|    |____|    |____|    |____
         *     ↑    ↓    ↑    ↓
         *     A    B    C    D
         *
         * */
        ECap1Regs.ECCTL1.bit.CAP1POL = 0;          // Rising edge  0
        ECap1Regs.ECCTL1.bit.CAP2POL = 1;          // Falling edge 1
        ECap1Regs.ECCTL1.bit.CAP3POL = 0;          // Rising edge  0
        ECap1Regs.ECCTL1.bit.CAP4POL = 1;          // Falling edge 1
        ECap1Regs.ECCTL1.bit.CTRRST1 = 0;          // 完成此次捕获后不重置计数器
        ECap1Regs.ECCTL1.bit.CTRRST2 = 0;          // 完成此次捕获后不重置计数器
        ECap1Regs.ECCTL1.bit.CTRRST3 = 0;          // 完成此次捕获后不重置计数器
        ECap1Regs.ECCTL1.bit.CTRRST4 = 1;          // 完成此次捕获后重置计数器
        ECap1Regs.ECCTL2.bit.SYNCI_EN = 1;         // Enable sync in
        ECap1Regs.ECCTL2.bit.SYNCO_SEL = 0;        // Pass through
        ECap1Regs.ECCTL1.bit.CAPLDEN = 1;          // Enable capture units
    
    
        ECap1Regs.ECCTL2.bit.CAP_APWM = 0;          //工作在CAP捕获模式
        ECap1Regs.ECCTL2.bit.REARM = 1;            // arm one-shot
        ECap1Regs.ECCTL1.bit.CAPLDEN = 1;          // Enable CAP1-CAP4 register loads
    //    ECap1Regs.ECEINT.bit.CEVT4 = 1;            // 4 events = interrupt
    
    //    ECap1Regs.ECCTL2.bit.TSCTRSTOP = 1;        // Start Counter
    }
    
    void InitECapture2()
    {
        ECap2Regs.ECEINT.all = 0x0000;             // Disable all capture interrupts
        ECap2Regs.ECCLR.all = 0xFFFF;              // Clear all CAP interrupt flags
        ECap2Regs.ECCTL1.bit.CAPLDEN = 0;          // Disable CAP1-CAP4 register loads
        ECap2Regs.ECCTL2.bit.TSCTRSTOP = 0;        // Make sure the counter is stopped
    
        // Configure peripheral registers
        ECap2Regs.ECCTL2.bit.CONT_ONESHT = 1;      // 单次模式
        ECap2Regs.ECCTL2.bit.STOP_WRAP = 3;        // Stop at 4 events
        ECap2Regs.ECCTL2.bit.SWSYNC = 1;            //同步所有的Ecap时钟
        //以下CAP2POL是配置捕获单元的极性
        /*
         *      ____      ____      ____
         *     |    |    |    |    |    |
         * ____|    |____|    |____|    |____
         *     ↑    ↓    ↑    ↓
         *     A    B    C    D
         *
         * */
        ECap2Regs.ECCTL1.bit.CAP1POL = 0;          // Rising edge  0
        ECap2Regs.ECCTL1.bit.CAP2POL = 1;          // Falling edge 1
        ECap2Regs.ECCTL1.bit.CAP3POL = 0;          // Rising edge  0
        ECap2Regs.ECCTL1.bit.CAP4POL = 1;          // Falling edge 1
        ECap2Regs.ECCTL1.bit.CTRRST1 = 0;          // 完成此次捕获后不重置计数器
        ECap2Regs.ECCTL1.bit.CTRRST2 = 0;          // 完成此次捕获后不重置计数器
        ECap2Regs.ECCTL1.bit.CTRRST3 = 0;          // 完成此次捕获后不重置计数器
        ECap2Regs.ECCTL1.bit.CTRRST4 = 1;          // 完成此次捕获后重置计数器
        ECap2Regs.ECCTL2.bit.SYNCI_EN = 1;         // Enable sync in
        ECap2Regs.ECCTL2.bit.SYNCO_SEL = 0;        // Pass through
        ECap2Regs.ECCTL1.bit.CAPLDEN = 1;          // Enable capture units
    
    
        ECap2Regs.ECCTL2.bit.CAP_APWM = 0;          //工作在CAP捕获模式
        ECap2Regs.ECCTL2.bit.REARM = 1;            // arm one-shot
        ECap2Regs.ECCTL1.bit.CAPLDEN = 1;          // Enable CAP1-CAP4 register loads
    //    ECap2Regs.ECEINT.bit.CEVT4 = 1;            // 4 events = interrupt
    
    //    ECap2Regs.ECCTL2.bit.TSCTRSTOP = 1;        // Start Counter
    }
    
    void InitECapture3()
    {
        ECap3Regs.ECEINT.all = 0x0000;             // Disable all capture interrupts
        ECap3Regs.ECCLR.all = 0xFFFF;              // Clear all CAP interrupt flags
        ECap3Regs.ECCTL1.bit.CAPLDEN = 0;          // Disable CAP1-CAP4 register loads
        ECap3Regs.ECCTL2.bit.TSCTRSTOP = 0;        // Make sure the counter is stopped
    
        // Configure peripheral registers
        ECap3Regs.ECCTL2.bit.CONT_ONESHT = 0;      // 连续模式
        ECap3Regs.ECCTL2.bit.STOP_WRAP = 1;        // Stop at 2 events
        ECap3Regs.ECCTL2.bit.SWSYNC = 1;            //同步所有的Ecap时钟
        //以下CAP3POL是配置捕获单元的极性
        /*
         *        ________
         *       |        |
         *  _____|        |________________________
         *       ↑        ↓
         *       A        B
         *
         * */
        ECap3Regs.ECCTL1.bit.CAP1POL = 0;          // Rising edge  0
        ECap3Regs.ECCTL1.bit.CAP2POL = 1;          // Falling edge 1
        ECap3Regs.ECCTL1.bit.CTRRST1 = 0;          // 完成此次捕获后不重置计数器
        ECap3Regs.ECCTL1.bit.CTRRST2 = 1;          // 完成此次捕获后重置计数器
    
        ECap3Regs.ECCTL2.bit.SYNCI_EN = 1;         // Enable sync in
        ECap3Regs.ECCTL2.bit.SYNCO_SEL = 0;        // Pass through
        ECap3Regs.ECCTL1.bit.CAPLDEN = 1;          // Enable capture units
    
    
        ECap3Regs.ECCTL2.bit.CAP_APWM = 0;          //工作在CAP捕获模式
        ECap3Regs.ECCTL2.bit.REARM = 1;            // arm one-shot
        ECap3Regs.ECCTL1.bit.CAPLDEN = 1;          // Enable CAP1-CAP4 register loads
        ECap3Regs.ECEINT.bit.CEVT2 = 1;            // 2 events = interrupt
    
        ECap3Regs.ECCTL2.bit.TSCTRSTOP = 1;        // Start Counter
    }
    
    
    
    /*******************************************************************************************************
     *  Ecap 的基准时钟在150MHz的主频下约为6.67ns
     *  也就是说每过6.67ns ECap1Regs.CAPx的值就会递增1,通过CAP1和CAP3的时间差可以计算出速度
     *******************************************************************************************************
     *  1. 该 E6B2-CWZ6C 的分辨率为 1000 P/R 即改编码器每转一圈,固定输出1000个脉冲
     *  2. 若1s内转一圈,则每个脉冲的周期为: 1s/1000 = 1ms (下图中A→C的时间 , 从  A → C 为一个完整的脉冲)
     *  3. 由 E6B2-CWZ6C 技术文档可知,输出一共有三相A、B、Z相输出,其中Z相为同步相
     *  4. 计算转速时只需要A相或者B相一个即可。但计算转动方向时,需要配合A相和B相,必须用到Z相,下面会解释
     *
     *     ____      ____      ____      ____
     *         |    |    |    |    |    |    |
     *         |____|    |____|    |____|    |____
     *         ↓    ↑    ↓    ↑
     *         A    B    C    D
     *
     *  当  A 事件(捕获第一个下降沿)发生时 Ecap模块把当前时间记录在 ECap1Regs.CAP1中
     *  当  B 事件(捕获第一个上升沿)发生时 Ecap模块把当前时间记录在 ECap1Regs.CAP2中
     *  当  C 事件(捕获第二个下降沿)发生时 Ecap模块把当前时间记录在 ECap1Regs.CAP3中
     *  当  D 事件(捕获第二个上升沿)发生时 Ecap模块把当前时间记录在 ECap1Regs.CAP4中
     *******************************************************************************************************
     *   下面说明一下正转和反转时的三相输出波形
     *
     *   捕获器1和2配置的
     *
     *   1. 正转(forward)
     *           _____       _____       _____
     *  A       |     |     |     |     |     |
     *     _____|     |_____|     |_____|     |_____...
     *          ↑     ↓     ↑     ↓
     *          A1    B1    C1    D1
     *
     *      以下变量可在函数中查看
     *      A1: Ecap1_TS1
     *      C1: Ecap1_TS3
     *               _____       _____       _____
     *  B           |     |     |     |     |     |
     *       _______|     |_____|     |_____|     |_____...
     *              ↑     ↓     ↑     ↓
     *              A2    B2    C2    D2
     *
     *      以下变量可在函数中查看
     *      A2: Ecap2_TS1
     *      B2: Ecap2_TS2
     *
     *          ___________
     *  Z      |           |
     *    _____|           |____________________________...
     *         ↑           ↓
     *         A3          B3
     *
     *      没用到Ecap3的计数寄存器
     *
     *   2. 反转(backward)
     *   标注见上
     *             _____       _____       _____
     *  A         |     |     |     |     |     |
     *       _____|     |_____|     |_____|     |_____...
     *            ↑     ↓     ↑     ↓
     *            A1    B1    C1    D1
     *          _____       _____       _____
     *  B      |     |     |     |     |     |
     *     ____|     |_____|     |_____|     |_____...
     *                     ↑     ↓     ↑     ↓
     *                     A2    B2    C2    D2
     *          ___________
     *  Z      |           |
     *    _____|           |____________________________
     *         ↑           ↓
     *         A3          B3
     *
     *
     *    需要注意,此种状态捕获模块捕获 B 相的上升沿如上图所示,而不是同步信号到来时的第一个上升沿
     *    应该是因为延时的原因,不影响测向。
     *
     *    同步相到来时,才会启动捕获模块1和2来捕获A相和B相的脉冲,捕获器完成一次捕获事件后就停止工作
     *    等待下一次的同步信号再一次启动捕获
     */
    __interrupt void ecap1_isr(void)
    {
        // 参考链接:https://blog.csdn.net/chenjiayu938/article/details/81349866
        ecap1_count = (++ ecap1_count) % 5;
    
        Ecap1_TS1 = ECap1Regs.CAP1;
        Ecap1_TS3 = ECap1Regs.CAP3;
    
        calc_pulse = Ecap1_TS3 - Ecap1_TS1;
        // calc_time unit is millseconds
        // 因为计数器每6.67ns递增一次,所以 ( 一个脉冲时间间隔内的计数器数值 ÷ 6.67 ) 就是一个脉冲持续的时间(ns),然后在除以1000000就换算得到ms
        // 此编码器的分辨率为 1000 P/R 转一圈固定输出1000个脉冲,1s转一圈输出的脉冲周期为1ms,因此可用   ( 1(ms) / 当前的脉冲周期(ms) )  来求得转速(r/s)
        calc_time = calc_pulse * 667.0 / 100.0 / 1000000.0;
        speed = 1 / calc_time;
    
    
        if(ecap1_count == 3)//降低刷新率,减小中断内部开销
        {
            memset(speed_char,'',8);
            doubleTochar(speed,speed_char,2);        //将浮点型speed数值转化为char型,用于LCD显示
            strcat(speed_char," r/s");
            memset(lcd_second_line,'',20);
            strcat(lcd_second_line," Speed:");
            strcat(lcd_second_line,speed_char);             //在"Speed:"后增添速度信息 最终信息格式为 "Speed:xx.xx r/s"
            if (Direction_flag == FORWARD) {
                Display_LCD1602(" Dire:forward",lcd_second_line);   //LCD1206显示速度和方向信息
            } else {
                Display_LCD1602(" Dire:backward",lcd_second_line);   //LCD1206显示速度和方向信息
            }
        }
    
        ECap1Regs.ECCLR.bit.CEVT4 = 1;      //使能第四级捕获事件发生后进入中断
        ECap1Regs.ECCLR.bit.INT = 1;        //清除Ecap全局中断标志位
        ECap1Regs.ECCTL1.bit.CAPLDEN = 1;   //使能在捕获事件中加载CAP1-4寄存器事件
    
        // Acknowledge this interrupt to receive more interrupts from group 4
        PieCtrlRegs.PIEACK.all = PIEACK_GROUP4;
    }
    
    
    __interrupt void ecap2_isr(void)
    {
    
        Ecap2_TS1 = ECap2Regs.CAP1;
        Ecap2_TS2 = ECap2Regs.CAP2;
    
        Ecap2_gap_A_B = Ecap2_TS1 - Ecap1_TS1;
        Ecap2_gap_pulse = Ecap2_TS2 - Ecap2_TS1;
    
        //判断方向
        if ( Ecap2_gap_A_B < Ecap2_gap_pulse) {
            Direction_flag = FORWARD;
        } else {
            Direction_flag = BACKWARD;
        }
    
        ECap2Regs.ECCLR.bit.CEVT4 = 1;
        ECap2Regs.ECCLR.bit.INT = 1;
        ECap2Regs.ECCTL1.bit.CAPLDEN = 1;          // Enable capture units
    
        // Acknowledge this interrupt to receive more interrupts from group 4
        PieCtrlRegs.PIEACK.all = PIEACK_GROUP4;
    }
    
    __interrupt void ecap3_isr(void)
    {
    
        if (Z_frist_flag == 0) {
            //Z相检测到同步信号,启动A相和B相的检测
            ECap1Regs.ECCTL2.bit.TSCTRSTOP = 1;//启动Ecap1定时器
            ECap2Regs.ECCTL2.bit.TSCTRSTOP = 1;//启动Ecap2定时器
            ECap1Regs.ECEINT.bit.CEVT4 = 1;// 4 events = interrupt
            ECap2Regs.ECEINT.bit.CEVT4 = 1;// 4 events = interrupt
            Z_frist_flag = 1;
        } else {
            //同步开启Ecap1和Ecap2
            ECap1Regs.ECCTL2.bit.REARM = 1;
            ECap2Regs.ECCTL2.bit.REARM = 1;
        }
    
    
        ECap3Regs.ECCLR.bit.CEVT2 = 1;
        ECap3Regs.ECCLR.bit.INT = 1;
        ECap3Regs.ECCTL2.bit.REARM = 1;
        ECap3Regs.ECCTL1.bit.CAPLDEN = 1;          // Enable capture units
    
        // Acknowledge this interrupt to receive more interrupts from group 4
        PieCtrlRegs.PIEACK.all = PIEACK_GROUP4;
    }
    
    

    维护日志

    维护日期 维护内容
    2019.07.14 增加了F2837xD系列DSP上的配置捕获输入GPIO的介绍
  • 相关阅读:
    软工实践练习一——使用Git进行代码管理心得
    作业1.3——Android平台的开发环境的发展演变
    作业1.2——软件工程的实践项目的自我目标
    SVN冲突解决
    sea.js及三种加载方式的异同
    php中AJAX请求中使用post和get请求的区别
    Vue-起步篇:Vue与React、 Angular的区别
    页面常见布局以及实现方法--flex
    requestAnimationFrame之缓动的应用
    bootstrap中table页面做省市区级联效果(级联库见前面级联编辑)(非select下拉框)
  • 原文地址:https://www.cnblogs.com/multimicro/p/9997615.html
Copyright © 2011-2022 走看看