初学DSP(2)-TMS320F280049C代码探究

 

英文缩写

  • C28X CPU+FPU(floating-point processor)
  • Trigonometric Math Unit (TMU)
  • Viterbi, Complex Math and CRC Unit (VCU)
  • Cyclic Redundancy Check (CRC)
  • start-of-conversion (SOC)

外设或通信协议

  • local interconnect network (LIN)
  • serial communication interface (SCI)
  • Controller Area Network (CAN)
  • Fast Serial Interface (FSI)
  • inter-integrated circuit (I2C)
  • serial peripheral interface (SPI)
  • enhanced pulse width modulator (ePWM)
     

寄存器编程的例程在C:\ti\c2000\C2000Ware_2_01_00_00\device_support\f28004x,

库函数编程的例程在C:\ti\c2000\C2000Ware_2_01_00_00\driverlib\f28004x\examples。

 

示例工程研究

实验参考的例程库函数版,主要针对ADC和CAN

例程是针对ControlCARD开发的,如果想将其应用到LaunchPad上,自然需要更改引脚映射。具体的代码可以在devices.h中找到。

芯片在上电或复位后会自动使能看门狗,所以初始化函数的第一句是将其关闭。

Register protection is enabled by default at startup. While protected, all writes to protected registers by the CPU
are ignored.
 

研究三个例子代码

  • // FILE:   led_ex1_blinky.c

//! This example demonstrates how to blink a LED.
//! If using LaunchPad, select build configuration for LAUNCHXL.

  • // FILE:   adc_ex1_soc_software.c

//! This example converts some voltages on ADCA and ADCB based on a software
//! trigger.

  • // FILE:   adc_ex3_temp_sensor.c

//! This example sets up the ePWM to periodically trigger the ADC.  The
//! ADC converts the internal connection to the temperature sensor,
//! which is then interpreted as a temperature by calling the
//! ADC_getTemperatureC() function.

 

 

  • // FILE:   can_ex1_loopback.c

//! This example shows the basic setup of CAN in order to transmit and receive
//! messages on the CAN bus.  The CAN peripheral is configured to transmit
//! messages with a specific CAN ID.  A message is then transmitted once per
//! second, using a simple delay loop for timing.  The message that is sent is
//! a 2 byte message that contains an incrementing pattern.

 

//led_ex1_blinky.c
void main(void)
{
    //设备初始化
    Device_init();   

    //设备引脚初始化 
    Device_initGPIO(); 

    //设备引脚配置   
    GPIO_setPadConfig(DEVICE_GPIO_PIN_LED1, GPIO_PIN_TYPE_STD);
    GPIO_setDirectionMode(DEVICE_GPIO_PIN_LED1, GPIO_DIR_MODE_OUT);

    //初始化并清除 PIE registers. 关闭 CPU interrupts. 
    Interrupt_initModule();

    // 初始化 PIE vector table ,指向 the shell Interrupt
    Interrupt_initVectorTable();

   
    // Enable Global Interrupt (INTM) and realtime interrupt (DBGM)
    EINT;
    ERTM;


    for(;;)
    {
  
        // Turn on LED
        GPIO_writePin(DEVICE_GPIO_PIN_LED1, 0);

        // Delay for a bit.
        DEVICE_DELAY_US(500000);

        // Turn off LED

        GPIO_writePin(DEVICE_GPIO_PIN_LED1, 1);

        // Delay for a bit.
        DEVICE_DELAY_US(500000);
    }
}
FILE:   adc_ex1_soc_software.c
void main(void)
{

    Device_init();
    Device_initGPIO();
    Interrupt_initModule();
    Interrupt_initVectorTable();

    // Set up ADCs, initializing the SOCs to be triggered by software
    initADCs();
    initADCSOCs();

    EINT;
    ERTM;

    while(1)
    {
        //
        // Convert, wait for completion, and store results
        //
        ADC_forceSOC(ADCA_BASE, ADC_SOC_NUMBER0);
        ADC_forceSOC(ADCA_BASE, ADC_SOC_NUMBER1);
        ADC_forceSOC(ADCB_BASE, ADC_SOC_NUMBER0);
        ADC_forceSOC(ADCB_BASE, ADC_SOC_NUMBER1);

        //
        // Wait for ADCA to complete, then acknowledge flag
        //
        while(ADC_getInterruptStatus(ADCA_BASE, ADC_INT_NUMBER1) == false)
        {
        }
        ADC_clearInterruptStatus(ADCA_BASE, ADC_INT_NUMBER1);

        //
        // Wait for ADCB to complete, then acknowledge flag
        //
        while(ADC_getInterruptStatus(ADCB_BASE, ADC_INT_NUMBER1) == false)
        {
        }
        ADC_clearInterruptStatus(ADCB_BASE, ADC_INT_NUMBER1);

        //
        // Store results
        //
        adcAResult0 = ADC_readResult(ADCARESULT_BASE, ADC_SOC_NUMBER0);
        adcAResult1 = ADC_readResult(ADCARESULT_BASE, ADC_SOC_NUMBER1);
        adcBResult0 = ADC_readResult(ADCBRESULT_BASE, ADC_SOC_NUMBER0);
        adcBResult1 = ADC_readResult(ADCBRESULT_BASE, ADC_SOC_NUMBER1);

        //
        // Software breakpoint. At this point, conversion results are stored in
        // adcAResult0, adcAResult1, adcBResult0, and adcBResult1.
        //
        // Hit run again to get updated conversions.
        //
        ESTOP0;
    }
}

 

//FILE:   adc_ex3_temp_sensor.c
void main(void)
{

    Device_init();

    Device_initGPIO();

    Interrupt_initModule();

    Interrupt_initVectorTable();

    //
    // Interrupts that are used in this example are re-mapped to ISR functions
    // found within this file.
    //
    Interrupt_register(INT_ADCB1, &adcB1ISR);

    //
    // Set up the ADC and the ePWM and initialize the SOC
    //
    initADC();
    initEPWM();
    initADCSOC();


    // Enable the temperature sensor and give it 500 us to power up
    ASysCtl_enableTemperatureSensor();
    DEVICE_DELAY_US(500);

    // Enable ADC interrupt
    Interrupt_enable(INT_ADCB1);


    // Enable Global Interrupt (INTM) and realtime interrupt (DBGM)
    EINT;
    ERTM;

    // Start ePWM1, enabling SOCA and putting the counter in up-count mode
    EPWM_enableADCTrigger(EPWM1_BASE, EPWM_SOC_A);
    EPWM_setTimeBaseCounterMode(EPWM1_BASE, EPWM_COUNTER_MODE_UP);


    while(1)
    {
        ;
    }
}
void main(void)
{
    uint16_t txMsgData[2], rxMsgData[2];


    Device_init();

    Device_initGPIO();
    GPIO_setPinConfig(DEVICE_GPIO_CFG_CANRXA);
    GPIO_setPinConfig(DEVICE_GPIO_CFG_CANTXA);

    //
    // Initialize the CAN controller
    //
    CAN_initModule(CANA_BASE);

    //
    // Set up the CAN bus bit rate to 500kHz
    // Refer to the Driver Library User Guide for information on how to set
    // tighter timing control. Additionally, consult the device data sheet
    // for more information about the CAN module clocking.
    //
    CAN_setBitRate(CANA_BASE, DEVICE_SYSCLK_FREQ, 500000, 20);


    Interrupt_initModule();
    Interrupt_initVectorTable();

    EINT;
    ERTM;

    //
    // Enable CAN test mode with external loopback
    //
    CAN_enableTestMode(CANA_BASE, CAN_TEST_EXL);

    //
    // Initialize the transmit message object used for sending CAN messages.
    // Message Object Parameters:
    //      Message Object ID Number: 1
    //      Message Identifier: 0x1234
    //      Message Frame: Standard
    //      Message Type: Transmit
    //      Message ID Mask: 0x0
    //      Message Object Flags: None
    //      Message Data Length: 2 Bytes
    //
    CAN_setupMessageObject(CANA_BASE, 1, 0x1234, CAN_MSG_FRAME_STD,
                           CAN_MSG_OBJ_TYPE_TX, 0, CAN_MSG_OBJ_NO_FLAGS,
                           MSG_DATA_LENGTH);

    //
    // Initialize the receive message object used for receiving CAN messages.
    // Message Object Parameters:
    //      Message Object ID Number: 2
    //      Message Identifier: 0x1234
    //      Message Frame: Standard
    //      Message Type: Receive
    //      Message ID Mask: 0x0
    //      Message Object Flags: None
    //      Message Data Length: 2 Bytes
    //
    CAN_setupMessageObject(CANA_BASE, 2, 0x1234, CAN_MSG_FRAME_STD,
                           CAN_MSG_OBJ_TYPE_RX, 0, CAN_MSG_OBJ_NO_FLAGS,
                           MSG_DATA_LENGTH);

    //
    // Start CAN module operations
    //
    CAN_startModule(CANA_BASE);

    //
    // Setup send and receive buffers
    //
    txMsgData[0] = 0x01;
    txMsgData[1] = 0x02;
    *(uint16_t *)rxMsgData = 0;

    //
    // Loop Forever - Send and Receive data continuously
    //
    for(;;)
    {
        //
        // Send CAN message data from message object 1
        //
        CAN_sendMessage(CANA_BASE, 1, MSG_DATA_LENGTH, txMsgData);

        //
        // Delay before receiving the data
        //
        DEVICE_DELAY_US(500000);

        //
        // Read CAN message object 2 and check for new data
        //
        if (CAN_readMessage(CANA_BASE, 2, rxMsgData))
        {
            //
            // Check that received data matches sent data.
            // Device will halt here during debug if data doesn't match.
            //
            if((txMsgData[0] != rxMsgData[0]) ||
               (txMsgData[1] != rxMsgData[1]))
            {
                Example_Fail = 1;
                asm("   ESTOP0");
            }
            else
            {
                //
                // Increment message received counter
                //
                msgCount++;
                Example_PassCount++;
            }
        }
        else
        {
            //
            // Device will halt here during debug if no new data was received.
            //
            Example_Fail = 1;
            asm(" ESTOP0");
        }

        //
        // Increment the value in the transmitted message data.
        //
        txMsgData[0] += 0x01;
        txMsgData[1] += 0x01;

        //
        // Reset data if exceeds a byte
        //
        if(txMsgData[0] > 0xFF)
        {
            txMsgData[0] = 0;
        }
        if(txMsgData[1] > 0xFF)
        {
            txMsgData[1] = 0;
        }
    }
}

总结基本共同的步骤

1、 Device_init(); //看门狗时钟

2、Device_initGPIO();  //实际只是解除锁定,没有真正配置

2.1  设置引脚模式

  •     GPIO_setPinConfig(DEVICE_GPIO_CFG_CANRXA);
  •     GPIO_setPinConfig(DEVICE_GPIO_CFG_CANTXA);

 

  •     GPIO_setPadConfig(DEVICE_GPIO_PIN_LED1, GPIO_PIN_TYPE_STD);
  •     GPIO_setDirectionMode(DEVICE_GPIO_PIN_LED1, GPIO_DIR_MODE_OUT);

3、外设初始化(可以包括引脚复用)

4、Interrupt_initModule();

5、Interrupt_initVectorTable();

6、// Enable Global Interrupt (INTM) and realtime interrupt (DBGM)  //开全局中断
    EINT;
    ERTM;

7、使能外设

 

通用函数说明

1、Device_init()函数的说明


// Function to initialize the device. Primarily initializes system control to a
// known state by disabling the watchdog, setting up the SYSCLKOUT frequency,
// and enabling the clocks to the peripherals.
// The function also configures the GPIO pins 22 and 23 in digital mode.
// To configure these pins as analog pins, use the function GPIO_setAnalogMode
 

2、GPIO引脚说明

在文件  FILE:   pin_map.h  定义了每个引脚并用的模式

在device.h里面的引脚宏定义都是来自  pin_map.h,往下就是寄存器地址了,寄存器编程。

以CAN协议为例

//from device.h
// CAN External Loopback
//
#define DEVICE_GPIO_CFG_CANRXA      GPIO_30_CANA_RX  // "pinConfig" for CANA RX
#define DEVICE_GPIO_CFG_CANTXA      GPIO_31_CANA_TX  // "pinConfig" for CANA TX
#define DEVICE_GPIO_CFG_CANRXB      GPIO_10_CANB_RX  // "pinConfig" for CANB RX
#define DEVICE_GPIO_CFG_CANTXB      GPIO_8_CANB_TX   // "pinConfig" for CANB TX
// form pin_map.h

#define GPIO_30_GPIO30                  0x00081C00U
#define GPIO_30_CANA_RX                 0x00081C01U
#define GPIO_30_SPIB_SIMO               0x00081C03U
#define GPIO_30_OUTPUTXBAR7             0x00081C05U
#define GPIO_30_EQEP1_STROBE            0x00081C06U
#define GPIO_30_SD1_D4                  0x00081C07U

#define GPIO_31_GPIO31                  0x00081E00U
#define GPIO_31_CANA_TX                 0x00081E01U
#define GPIO_31_SPIB_SOMI               0x00081E03U
#define GPIO_31_OUTPUTXBAR8             0x00081E05U
#define GPIO_31_EQEP1_INDEX             0x00081E06U
#define GPIO_31_SD1_C4                  0x00081E07U
#define GPIO_31_FSIRXA_D1               0x00081E09U

GPIO配置函数细究

GPIO_setPinConfig(DEVICE_GPIO_CFG_CANRXA);

from device.h

#define DEVICE_GPIO_CFG_CANRXA      GPIO_30_CANA_RX  // "pinConfig" for CANA RX
#define DEVICE_GPIO_CFG_CANTXA      GPIO_31_CANA_TX  // "pinConfig" for CANA TX
#define DEVICE_GPIO_CFG_CANRXB      GPIO_10_CANB_RX  // "pinConfig" for CANB RX
#define DEVICE_GPIO_CFG_CANTXB      GPIO_8_CANB_TX   // "pinConfig" for CANB TX

GPIO_setPinConfig(uint32_t pinConfig);

//! Configures the alternate function of a GPIO pin.
//!
//! \param pinConfig is the pin configuration value, specified as only one
//! of the \b GPIO_#_???? values.
//!
//! This function configures the pin mux that selects the peripheral function
//! associated with a particular GPIO pin.  Only one peripheral function at a
//! time can be associated with a GPIO pin, and each peripheral function should
//! only be associated with a single GPIO pin at a time (despite the fact that
//! many of them can be associated with more than one GPIO pin).

 

GPIO_setPadConfig(DEVICE_GPIO_PIN_LED1, GPIO_PIN_TYPE_STD);

from device.h

#define DEVICE_GPIO_PIN_LED1        31U  // GPIO number for LD2
#define DEVICE_GPIO_PIN_LED2        34U  // GPIO number for LD3
#define DEVICE_GPIO_CFG_LED1        GPIO_31_GPIO31  // "pinConfig" for LD2
#define DEVICE_GPIO_CFG_LED2        GPIO_34_GPIO34  // "pinConfig" for LD3

GPIO_setPadConfig(uint32_t pin, uint32_t pinType)

//! Sets the pad configuration for the specified pin.
//!
//! \param pin is the identifying GPIO number of the pin.
//! \param pinType specifies the pin type.
//!
//! This function sets the pin type for the specified pin. The parameter
//! \e pinType can be the following values:
//!
//! - \b GPIO_PIN_TYPE_STD specifies a push-pull output or a floating input
//! - \b GPIO_PIN_TYPE_PULLUP specifies the pull-up is enabled for an input
//! - \b GPIO_PIN_TYPE_OD specifies an open-drain output pin
//! - \b GPIO_PIN_TYPE_INVERT specifies inverted polarity on an input

 

GPIO_setDirectionMode(DEVICE_GPIO_PIN_LED1, GPIO_DIR_MODE_OUT);

GPIO_setDirectionMode(uint32_t pin, GPIO_Direction pinIO);

//*****************************************************************************
//
//! Sets the direction and mode of the specified pin.
//!
//! \param pin is the identifying GPIO number of the pin.
//! \param pinIO is the pin direction mode.
//!
//! This function configures the specified pin on the selected GPIO port as
//! either input or output.
//!
//! The parameter \e pinIO is an enumerated data type that can be one of the
//! following values:
//!
//! - \b GPIO_DIR_MODE_IN
//! - \b GPIO_DIR_MODE_OUT
//!
//! where \b GPIO_DIR_MODE_IN specifies that the pin is programmed as an input
//! and \b GPIO_DIR_MODE_OUT specifies that the pin is programmed as an output.
//!
//! The pin is specified by its numerical value. For example, GPIO34 is
//! specified by passing 34 as \e pin.
 

#define DEVICE_GPIO_PIN_CANTXA      31U  // GPIO number for CANTXA(引脚号)

#define DEVICE_GPIO_CFG_CANRXA      GPIO_30_CANA_RX  // "pinConfig" for CANA RX(引脚配置,pin_map.h文件中)

//*****************************************************************************
#define GPIO_PIN_TYPE_STD       0x0000U //!< Push-pull output or floating input
#define GPIO_PIN_TYPE_PULLUP    0x0001U //!< Pull-up enable for input
#define GPIO_PIN_TYPE_INVERT    0x0002U //!< Invert polarity on input
#define GPIO_PIN_TYPE_OD        0x0004U //!< Open-drain on output
#endif

//*****************************************************************************
//
//! Values that can be passed to GPIO_setDirectionMode() as the \e pinIO
//! parameter and returned from GPIO_getDirectionMode().
//
//*****************************************************************************
typedef enum
{
    GPIO_DIR_MODE_IN,                   //!< Pin is a GPIO input
    GPIO_DIR_MODE_OUT                   //!< Pin is a GPIO output
} GPIO_Direction;

 

设置引脚GPIO和设置引脚复用,gpio.h

GPIO输入输出:

    GPIO_setPadConfig(DEVICE_GPIO_PIN_LED1, GPIO_PIN_TYPE_STD);
    GPIO_setDirectionMode(DEVICE_GPIO_PIN_LED1, GPIO_DIR_MODE_OUT);

GPIO_writePin(DEVICE_GPIO_PIN_LED1, 0);

GPIO_readPin(uint32_t pin)

GPIO复用:

    GPIO_setPinConfig(DEVICE_GPIO_CFG_CANRXA);
    GPIO_setPinConfig(DEVICE_GPIO_CFG_CANTXA);

 

C2000 驱动文件层次研究

(最好把文件打开对比着看,对文件结构里理解很到位,再配合上一篇建立工程,更好的理解了)

device.c,device.h ,driverlib.h 都是是TI做好的库函数  

device.h  设备的引脚宏定义

driverlib.h 设备外设驱动的声明

//from devicelib.h

#include "inc/hw_memmap.h"

#include "adc.h"
#include "asysctl.h"
#include "can.h"
#include "cla.h"
#include "clb.h"
#include "clapromcrc.h"
#include "cmpss.h"
#include "cpu.h"
#include "cputimer.h"
#include "dac.h"
#include "dcc.h"
#include "dcsm.h"
#include "debug.h"
#include "dma.h"
#include "ecap.h"
#include "epwm.h"
#include "eqep.h"
#include "flash.h"
#include "fsi.h"
#include "gpio.h"
#include "hrcap.h"
#include "hrpwm.h"
#include "i2c.h"
#include "interrupt.h"
#include "lin.h"
#include "memcfg.h"
#include "pga.h"
#include "pin_map.h"
#include "pin_map_legacy.h"
#include "pmbus.h"
#include "sci.h"
#include "sdfm.h"
#include "spi.h"
#include "sysctl.h"
#include "version.h"
#include "xbar.h"

开头的 hw_memmap.h

// FILE:    hw_memmap.h
//
// TITLE:   Macros defining the memory map of the C28x.

最底层的寄存器宏定义,是E:\ti\c2000\C2000Ware_3_03_00_00\driverlib\f28004x\driverlib\inc,hw前缀的文件

// FILE:    hw_adc.h
//
// TITLE:   Definitions for the ADC registers.

再往上是 E:\ti\c2000\C2000Ware_3_03_00_00\driverlib\f28004x\driverlib  各种外设驱动文件

往上又是 E:\ti\c2000\C2000Ware_3_03_00_00\device_support\f28004x\common\include  的各种外设应用文件

编程时,写这两句,就把外设的驱动包括进来了

#include "driverlib.h"
#include "device.h"

再在工程中添加文件索引

E:\ti\c2000\C2000Ware_3_03_00_00\driverlib\f28004x\driverlib

在driverlib.h里面开头,#include "inc/hw_memmap.h",表示当前路径下inc文件夹里的hw_memmap.h,所以复制文件需要整个E:\ti\c2000\C2000Ware_3_03_00_00\driverlib\f28004x\driverlib下 的文件

再可以打开被#include "driverlib.h"引用的adc.h文件 ,开头就声明了,

#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_adc.h"
#include "inc/hw_asysctl.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "cpu.h"
#include "debug.h"

发现 #include <stdbool.h> 这个文件就是编译器带的头文件了

所以需要在工程中添加文件索引

E:\ti\ccs1011\ccs\tools\compiler\ti-cgt-c2000_20.2.1.LTS\include

 

 

使用ADC与CAN外设初始化函数细究

//驱动里面没有这个函数,需要自己写
// initADCs - Function to configure and power up ADCs A and B.
//
void initADCs(void)
{
    //
    // Setup VREF as internal
    //
    ADC_setVREF(ADCA_BASE, ADC_REFERENCE_INTERNAL, ADC_REFERENCE_3_3V);
    ADC_setVREF(ADCB_BASE, ADC_REFERENCE_INTERNAL, ADC_REFERENCE_3_3V);

    //
    // Set ADCCLK divider to /4
    //
    ADC_setPrescaler(ADCA_BASE, ADC_CLK_DIV_4_0);
    ADC_setPrescaler(ADCB_BASE, ADC_CLK_DIV_4_0);

    //
    // Set pulse positions to late
    //
    ADC_setInterruptPulseMode(ADCA_BASE, ADC_PULSE_END_OF_CONV);
    ADC_setInterruptPulseMode(ADCB_BASE, ADC_PULSE_END_OF_CONV);

    //
    // Power up the ADCs and then delay for 1 ms
    //
    ADC_enableConverter(ADCA_BASE);
    ADC_enableConverter(ADCB_BASE);

    DEVICE_DELAY_US(1000);
}
    from can.h
//
    // Initialize the CAN controller
    //
    CAN_initModule(CANA_BASE);

 TI的外设初始化也是醉了,ADC初始化自己写个函数,SPI外设,建了个E:\CCS_workplace\spi_ex1_loopback\CPU1_RAM\syscfg  board.c,board.h

使用外设之前可以先看看示例工程,这样还方便一下

 

中断触发方法的研究

中断优先级

 

  • 8
    点赞
  • 53
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大大U

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值