DSP28335的SCI的FIFO中断使用心得

自学了一段时间的DSP28335的串口设置,写下来帮助更多的新手,遇到了很多问题也记录一些解决办法。

以下全都是我个人的理解,可能说的不对,大家讨论。

1、关于为什么必须用FIFO

一般的DSP系统,尤其是控制类的,都要使用串口FIFO。如果不用FIFO,假设传八个数据包(也就是八帧数据)要进八次中断,非常影响主函数的控制效果。用FIFO的话,让数据在FIFO等待(可以理解为一个长空间,暂时存放数据用的临时场所),进一次中断就可以了。

2、串口以及FIFO的设置

这个到处都能查得到,找个中文手册一步一步设置就行了

注意几个我遇到的坑

(1)SCI的每一个数据包最多可以包含8位数据(也就是8个二进制,就是0和1嘛),这个在SCICCR这个寄存器设置;

(2)SCI的FIFO最多可以收发16个数据包,但是这个设置也有讲究,在SCIFFTX和SCIFFRX李设置,其中TXFFST和RXFFST叫状态位,TXFFIL和RXFFIL叫深度,他们都是用5位数据来设定的,我最开始把16理解成11111了,其实应该是10000;

(3)尽量在DSP别用除法,用移位去运算;

(4)中断那得好好学,按照流程设置,先是各种初始化,然后设置串口的波特率与寄存器配置,然后确定中断函数的入口,(搞清楚串口的ABC用的到底是哪个,很关键,不然调程序这种小错很烦人)然后使能中断,具体使能哪条线路,得去查PIE的一张表,网上都有,最后使能CPU级别的中断,就是IER,别忘了用或运算,例如  IER |= M_INT9;

3、FIFO使用的一些问题

先放代码。

void main()
{
    int i;
    InitSysCtrl();
    InitGpio();
    InitSciGpio();
    InitPieCtrl();
    DINT;
    IER = 0x0000;// 禁用 CPU 中断和清除所有 CPU 中断标志位:
    IFR = 0x0000;

    InitPieVectTable();

    SCI_Init(9600);

    EALLOW;        // This is needed to write to EALLOW protected registers
    PieVectTable.SCIRXINTB = &ScibRxFifoIsr;
    PieVectTable.SCITXINTB = &ScibTxFifoIsr;
    EDIS;   // This is needed to disable write to EALLOW protected registers

    PieCtrlRegs.PIECTRL.bit.ENPIE = 1;   // Enable the PIE block
    PieCtrlRegs.PIEIER9.bit.INTx3=1;     // PIE Group 9, INT3
    PieCtrlRegs.PIEIER9.bit.INTx4=1;

    IER |= M_INT9; // Enable CPU INT9--- SCIA/B     INT8--- SCIC/D
    IER |= M_INT1; //定时器0//或运算不干扰其他中断

    EINT;//使能全局中断
    ERTM;//使能全局实时中断

    for(i = 0; i<12; i++) //缓存初始化
    {
        buffer[i] = '0';
    }

    while(1)
    {

    }
}

void SCI_Init(Uint32 baud)
{
    unsigned char sci_h_baud = 0;
    unsigned char sci_l_baud = 0;
    Uint16 sci_baud = 0;

    sci_baud = 37500000 / (8 * baud) - 1;//baud是输入的波特率
    sci_h_baud = sci_baud >> 8;
    sci_l_baud = sci_baud & 0xff;//按位与运算,均为1才能为1,0000 0000 1111 1111

    EALLOW;
    SysCtrlRegs.PCLKCR0.bit.SCIBENCLK = 1;//SCIB使能
    EDIS;

    ScibRegs.SCICCR.all = 0x0007;

    ScibRegs.SCIHBAUD = sci_h_baud;
    ScibRegs.SCILBAUD = sci_l_baud;
    //功能初始化
    ScibRegs.SCICTL1.all = 0x0003; // enable TX, RX, internal SCICLK,
                                   // Disable RX ERR, SLEEP, TXWAKE
    ScibRegs.SCICTL2.all = 0x0003;
    //FIFO初始化
    ScibRegs.SCIFFTX.all = 0xC028;
    ScibRegs.SCIFFRX.all = 0x0028;

    ScibRegs.SCIFFCT.all = 0x0000;

    ScibRegs.SCICTL1.all = 0x0023;
    ScibRegs.SCIFFTX.bit.TXFIFOXRESET=1;    // 重新使能发送FIFO的操作
    ScibRegs.SCIFFRX.bit.RXFIFORESET=1;     // 重新使能接收FIFO的操作
}
//----------------------------------------------------------

interrupt void ScibTxFifoIsr(void) //fifo发送中断服务子程序

{
    Uint16 i;
    for(i=0;i<8; i++)
    {
        ScibRegs.SCITXBUF=buffer[i];     // Send data 将缓存中的数据发出
    }
    PieCtrlRegs.PIEACK.all|=PIEACK_GROUP9;      // Issue PIE ACK
}

interrupt void ScibRxFifoIsr(void)//fifo接收中断服务子程序
{
    Uint16 i;
    for(i=0; i<8; i++)
    {
        buffer[i]=ScibRegs.SCIRXBUF.all; // 将fifo中的数据读到缓存
    }
    ScibRegs.SCIFFTX.bit.TXFFINTCLR=1;  // 很重要 若不清fifo发送中断标志则,不进入发送中断
    ScibRegs.SCIFFRX.bit.RXFFINTCLR=1; // 清接收中断标志
    PieCtrlRegs.PIEACK.all|=PIEACK_GROUP9;    // Issue PIE ack
}

这个代码的变量声明部分不全,懒得粘了,自己补一下吧~尽量用全局变量,也好用仿真器观察

函数的流程是

(1)从上位机发8个数据包到RX,每发一个包,RXFFST这个状态位就加1,加到8,与设置的接收深度相等了,就跳入接收中断里,然后给buffer这个数组赋值,for循环每走一次,状态位就减1,最终减到0,意味着接收FIFO里没数据了,这时候for循环也跳出了。然后两个清零标志位置1,这个得好好理解,看看书也好懂。(可以自己试试for循环不跑8次是啥结果)

然后最后响应PIE级中断,这个语句执行完,CPU才算真的收到数据了,保存在内存了。

(2)然后准备从发送发出来。一定要明白发送和接收是一个反过程,这时先给寄存器赋值,然后再进入FIFO,这里有个小细节,比如发进去的是‘AAAA   AAAB’,按顺序的八个字符。执行完发送中断里的for循环后,在SCITXBUF里的是‘B’,此时TXFFST状态位是7,并不是8。然后执行完PIE以后串口发出,显示在上位机里。该过程遵循FIFO的先入先出原则。发送完以后标志位自动置1

想下次再进入中断,就得根据清除标志位是0还是1了。如果置1,说明标志位被清除,这时就自动又跳入发送中断了。

这点东西其实很浅显,但是也花费了一些精力琢磨整个流程,多改动关键代码自己研究吧

  • 37
    点赞
  • 171
    收藏
    觉得还不错? 一键收藏
  • 13
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值