Matlab生成dsp程序——官方例程学习(5)


官方链接: 官方链接
模型及其程序: 模型及程序

一、基本目的

    官方例程中写的是使用IIC与传感器进行通信。因为与具体的官方给的传感器传输协议有一些关系,因此着重看每个模块的功能和大致结构。

在这里插入图片描述

二、IIC通信基本原理

   IIC通信是两线通信(SDA与SCL),属于半双工的通信方式。I2C协议包括:1.空闲信号 2.开始信号 3.停止信号 4.应答信号 5.数据的有效性 6.数据传输

1)空闲状态

SDA与SCL信号同时处于高电平。

2)起始信号和停止信号

在这里插入图片描述

起始信号:SCL为高时,SDA由高到底的跳变
停止信号:SCL为高时,SDA由低到高的跳变

3)应答信号
 每发送八位,在第九个时钟脉接收应答信号(应答信号为低电平时,表示成功接收,反之亦然),即SCL第九个脉冲之前,必须将SDA拉低。

4)数据有效性

  IIC进行数据传送时,SCL为高电平时,SDA必须保持稳定(不允许发生跳变)。只有SCL为低电平时,SDA才能发送变化

在这里插入图片描述

5)数据的传送

 SDA每传送一位与一个时钟脉冲进行对应,SCL为高时进行传送。

三、具体实现

 因为SDA作为数据线,所有有发送和接收两种状态,相对应需要设置GPIO为输入和输出两种状态。

#define IIC_SCL PBout(6)
#define IIC_SDA PBOUT(7)
#define READ_SDA PBin(7)

void IIC_init()  //IIC初始化函数
{
    1.设置相应的GPIO管脚的工作模式(开始都置为推挽输出模式)
        2.将SCL与SDA置为高电平(进入空闲模式)
}

void IIC_start() //IIC开始信号函数
{
    SDA_OUT();
    IIC_SDA=1;
    IIC_SCL=1;
    DELAY_US(10);
    IIC_SDA=0;         //开始信号完毕
    DELAY_US(10);
    IIC_SCL=0;         //将SCL置为低,开始准备SDA的数据
}

void IIC_stop()      //停止信号函数
{
    SDA_OUT();
    IIC_SDA=0;
    IIC_SCL=0;
    DELAY_US(10);
    IIC_SCL=1;
    IIC_SDA=1;         //停止信号完毕
    DELAY_US(10);
}

int ACK() //接收应答信号
{
    int times;
    SDA_IN();
    
    IIC_SDA=1; 
    DELAY_US(10);
    
    IIC_SCL=1;
    DELAY_US(10);
    while(READ_SDA)    //若接收为低电平则不进while,为高							//则继续等待
    {
        times++;
        if(times >250
           {
               IIC_stop();
               return 1;
           }
    }
    IIC_SCL=0;
    return0;  
}

void IIC_ACK() //发送应答信号(作为接收)
{
   IIC_SCL=0;
   SDA_OUT();
   IIC_SDA=0; 
   DELAY_US(10);
   IIC_SCL=1;
   DELAY_US(10);
   IIC_SCL=0;
}

 void Send_byte(usigned int t) //发送一个字节
{
   int i;
   SDA_OUT();
   IIC_SCL=0;
   
   for(i=0;i<8;i++)
   {
       if(t&0x80>>7)
           IIC_SDA=1;
       else
           IIC_SDA=0;
       t<<=1;
       DELAY_US(10);
       IIC_SCL=1;
       DELAY_US(10);
       IIC_SCL=0;
       DELAY_US(10);
   }
       
}
           
void Rev_bytes()
{
   int i;
   unsigned char rev=0;
   SDA_IN();
   
   for(i=0;i<8;i++)
   {
       IIC_SCL=0;
       DELAY_US(10);
       IIC_SCL=1;
       
       rev<<=1;
       if(READ_SDA)
           rev++;
       DELAY_US(10);
   }
   IIC_ACK();   //发送应答信号
}

  以上只是IIC的底层函数,使用还是需要结合具体器件进行查看器件协议。

四、生成代码与模型分析

主要分析一下Timer0中断函数中的程序:

void rt_OneStep(void)
{
  boolean_T eventFlags[3];
  int_T i;

  /* Check base rate for overrun */
  if (isRateRunning[0]++) {
    IsrOverrun = 1;
    isRateRunning[0]--;                /* allow future iterations to succeed*/
    return;
  }

  /*
   * For a bare-board target (i.e., no operating system), the rates
   * that execute this base step are buffered locally to allow for
   * overlapping preemption.  The generated code includes function
   * writeCodeInfoFcn() which sets the rates
   * that need to run this time step.  The return values are 1 and 0
   * for true and false, respectively.
   */
  c28x_i2c_sensor_SetEventsForThisBaseStep(eventFlags);
  enableTimer0Interrupt();
  c28x_i2c_sensor_step0();

  /* Get model outputs here */
  disableTimer0Interrupt();
  isRateRunning[0]--;
  for (i = 1; i < 3; i++) {
    if (eventFlags[i]) {
      if (need2runFlags[i]++) {
        IsrOverrun = 1;
        need2runFlags[i]--;            /* allow future iterations to succeed*/
        break;
      }
    }
  }

  for (i = 1; i < 3; i++) {
    if (isRateRunning[i]) {
      /* Yield to higher priority*/
      return;
    }

    if (need2runFlags[i]) {
      isRateRunning[i]++;
      enableTimer0Interrupt();

      /* Step the model for subrate "i" */
      switch (i)
      {
       case 1 :
        c28x_i2c_sensor_step1();

        /* Get model outputs here */
        break;

       case 2 :
        c28x_i2c_sensor_step2();

        /* Get model outputs here */
        break;

       default :
        break;
      }

      disableTimer0Interrupt();
      need2runFlags[i]--;
      isRateRunning[i]--;
    }
  }
}
    1. 建立一个 unsigned int 数组(长度为3)eventFlags[3],建立一个 int 型数据i
    1. 当isRateRunning[0]大于1时,将IsrOverrun置为1,然后直接退出函数。这里是检验是否满足进入函数的条件。isRateRunning[0]自加1。
    1. 将eventFlags[1]赋值为 (c28x_i2c_sensor_M)->Timing.TaskCounters.TID[1] == 0
    1. 将eventFlags[2]赋值为 (c28x_i2c_sensor_M)->Timing.TaskCounters.TID[2] == 0
  • //c28x_i2c_sensor_M结构体中包含一个errorStatus指针、一个Timing结构体(里面包括TaskCounters结构体(包含一个TID[3])、RateInteraction结构体(包含一个变量TID0_1))
    
    struct tag_RTM_c28x_i2c_sensor {
      const char_T *errorStatus;
    
      /*
       * Timing:
       * The following substructure contains information regarding
       * the timing information for the model.
       */
      struct {
        struct {
          uint8_T TID[3];
        } TaskCounters;
    
        struct {
          boolean_T TID0_1;
        } RateInteraction;
      } Timing;
    };
    
  • 5)开Timer0中断

  • 6)进入**c28x_i2c_sensor_step0()**函数。

  • 7)关Timer0中断

  • 8)后面的部分指的是,经过判断==eventFlags[i]need2runFlags[i]以及isRateRunning[i]==的值,先执行c28x_i2c_sensor_step1()、再执行c28x_i2c_sensor_step2()

  下面看**c28x_i2c_sensor_step0()函数,c28x_i2c_sensor_B.I2CReceive_o1[]中存储收到的数据c28x_i2c_sensor_B.I2CReceive_o2中存储受到的变量。8位进行的接收,强制转换为16位数据存放在c28x_i2c_sensor_B.DataTypeConversion[]**中。然后进行发送一个
c28x_i2c_sensor_P.DataReadAdress_Value中的地址。
这一块对应的是模型中这一部分的内容:

在这里插入图片描述

  **c28x_i2c_sensor_step1()**中对应初始化函数:

在这里插入图片描述

  **c28x_i2c_sensor_step2()**中对应初始化函数:

在这里插入图片描述

五、代码逻辑

step0需要每次循环都执行,即读取数据。然后执行c28x_i2c_sensor_step1()(发送指令)和c28x_i2c_sensor_step2()(转换数据格式)函数。

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Quikk

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

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

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

打赏作者

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

抵扣说明:

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

余额充值