搜索
bottom↓
回复: 1

McBSP配置成Uart的具体实现(基于5509)

[复制链接]

出0入0汤圆

发表于 2013-12-24 20:51:39 | 显示全部楼层 |阅读模式
本帖最后由 xhyzjiji 于 2013-12-24 20:55 编辑

在此声明一下,这里是基于5509型号的dsp,其他型号可能在McBSP功能上有些区别,但原理大致通用。
1.McBSP资源及支持的工作模式
5509的McBSP具有双缓冲发送,三缓冲接收,支持全双工通信;支持独立的(由内部产生或外部输入的)收发时钟信号(CLKX、CLKR)和帧同步信号(FSX、FSR);128通道时分复用;支持DMA触发事件和中断触发;传输字的长度(字长)可以是8、12、16、20、24、32位,一次可传输1~128个字(帧长);支持数据压缩和符号扩展功能;McBSP引脚可设置位通用IO口。
McBSP可以配置成的模式包括:GPIO模式、SPI模式、I2S模式、多通道模式。
关于多通道
多通道一般用作时分复用,帧长指定一次传输应该传输多少个字,等同于传输给多少个通道(每个通道可以接收一个字)。由于传输顺序默认从通道1~通道128,且通道使能是可以自定义的,因此帧长度设置必须大于或等于已经使能的通道中最大的通道号。例如:我使能了第0、15、39通道,McBSP一帧内将接收39个字,现在开始传输字0、字2……字N,McBSP通道0接收字0,通道15接收字15,通道39接收字39,但只有真正使能后的通道才有相应的硬件动作。详细见《TMS320VC5501/5502/5509/5510 DSP Multichannel Buffered Serial Port (McBSP) Reference Guide》的5.3一节。

2.McBSP的硬件引脚连接
假设使用McBSP1
McBSP1.DR和McBSP1.FSR作为数据接收端,McBSP1.DX作为数据发送端。
串口属于异步通信,因此数据时钟均不需要,但这里使用了McBSP1.FSR连接到数据接收端,是因为串口数据存在开始位,并强制将数据总线由高电平拉低,这个可以作为接收帧同步信号;而发送帧同步信号FSX在这里不需要,可以悬空。

3.传输原理
以前,使用单片机上的片上外设UART十分简单,计算波特率时钟以及配置所属寄存器就可以进行通信。由于McBSP属于同步串行通信设备,且dsp的速度远远高于串口通信的速度,因此需要使用过采样-->解码进行接收。
过采样原理与作用
过采样就是dsp对串口传输字节中每一个位进行多次采样,并根据采样值进行判决。如:这里使用16倍于波特率的过采样率,对串口数据进行过采样,由于dsp接收起始时间并非严格对齐起始位的下降沿,所以,数据位为1,并非每次过采样都可以检测到数据线电平为1,但当一位数据检测,采样到1的次数大于过采样率的一般,则认为该位为1,否则认为该位为0。(有同学可以提供个好用的画图工具吗?)
过采样的好处就是可以消除连续传输时候的延时累加。


传输具体步骤如下:
1.在通信对象发送开始位时,DR和FSR被拉低,低电平触发帧同步信号,McBSP接收器开始接收数据(接收器工作时钟由dsp内部时钟分频得到),由于串口数据常用帧结构为:开始位、8为数据位、停止位(1bit)(如果使用停止位为1.5bit或者2bit,需要使用多相位多通道传输方式),由于16倍波特率的过采样率,所以需要设置字长为16位。每当对一位采样完成或者整个字节传输完成(可选)时,随即进行解码。
2.将需要发送的字节扩展成10个16位数据,以接收器使用时钟将并行数据串行地发送出去即可。
明显地,发送比接收要简单得多;为尽量降低CPU使用率,我们可以使用DMA和中断方式使CPU尽可能不干涉数据的传输。这里纯粹以最简单方法进行实现,所以暂不使用DMA和中断。

4.存储器配置(不提及的寄存器位可以按复位默认值)
SPCR1寄存器
DLB(15)=0;//关闭回环模式    RJUST(14-13)=00b;//数据右对齐,高位补0    CLKSTP(12-11)=0;//数据传输结束时,不关闭发送/接收时钟    DXENA(7)=1;//dsp发送数据开始后,将延时一段时间后DX才输出数据    RRST(0)=1;//使能接收器
SPCR2寄存器
FRST(7)=1;//由CLKG分频(FPER)后产生帧同步信号    GRST(6)=1;//由采样率发生器产生CLKG    XRST(0)=1;//使能发送器
SRGR1寄存器
FWID(15-8)=0x01;//帧同步信号FSG的脉冲宽度为1个CLKG    CLKGDV(7-0)=CLKGDV_38400;//16倍过采样率,每个串口帧数据采样10位数据,经过160个CLKG时钟,因此决定接收时钟=DSP时钟/波特率/16-(1~5),以下是在144MHz的DSP主频下,经测试可用的CLKGDV值:
#define CLKGDV_115200 (0x004Du)
#define CLKGDV_57600   (0x009Bu)
#define CLKGDV_56000   (0x00A0u)
#define CLKGDV_38400   (0x00E8u)
SRGR2寄存器
CLKSM(13)=1;//选择dsp时钟作为采样率发生器    FSGM(12)=1;//发送帧同步信号使用FSG触发(FSXM=1,FSGM=0:当DXR内容被复制到XSR时,产生一个发送帧同步,FSXM=1,FSGM=1:发送帧同步信号由CLKG分频得到)    FPER(11-0)=160;//一帧传输中需要过采样率*串口传输帧位数,这里为16*10=160
PCR寄存器
IDLEEN(14)=0;//取消省电模式    FSXM(11)=1;//发送帧同步由内部FSG提供    FSRM(10)=0;//接收帧同步有FSR引脚提供    CLKXM(9)=1;//发送器时钟使用内部产生的CLKG    CLKRM(8)=1;//接收器时钟使用内部产生的CLKG    SCLKME(7)=0;//与SCLKME CLKSM=0 0时,采样发生器输入时钟选择CPU时钟   
R(X)CR1寄存器
R(X)FRLEN1(14-8)=9;//设置阶段1帧长为10个字(R(X)FRLEN1+1)    R(X)WDLEN1(7-5)=15;//设置阶段1字长为16位(R(X)WDLEN1+1)   
R(X)CR2寄存器
R(X)COMPAND(4-3)=00b;//高位先接受    RFIG(2)=0;//忽略第一个帧同步过后的帧同步信号,这里非常重要    XFIG(2)=1;//当数据移入发送寄存器后,产生发送帧同步信号,发送器开始工作    RDATDLY(1-0)=0;//从接受帧同步产生后不进行延时立即开始将数据移入接收寄存器    XDATDLY(1-0)=1;//从发送帧同步产生后延时一个CLKG时钟后开始发送数据   
MCR1/2寄存器
R(X)MCME(9)=1;//使能128各通道并可以由R(X)CER指定使能通道    R(X)MCM(0)=1;//可以独立使能通道
R(X)CERA = 0x03FF;  //使能通道0-9

5.过采样解码
过采样解码则对过采样得到的接收数据,判断数据中1的个数进行判别。由于16倍过采样率,因此对接收数据(16位)进行1的位数统计,如0x33,则'1'的统计数为4
unsigned int bitscan(unsigned int char_data){
        unsigned int num=0;
        while(char_data){
                char_data &= (char_data-1);
                num++;
        }
        return num;
}
这里的算法复杂度为log2(n),具体算法原理可以参考《编程之美》。
unsigned int rxbuf[10];
void char2rxbuf(unsigned int char_data){
        unsigned int i;
        unsigned int temp = 0x00FF&char_data;
        for(i=0; i<8; i++){
                //串口传输顺序:起始位,数据低位--数据高位,校验位(这里不用),停止位
                if(temp&(0x0001<<i))
                        rxbuf[i+1] = 0xFFFF;
                else
                        rxbuf[i+1] = 0x0000;
        }
}
这里将需要发送的8位数据进行扩展并存入发送缓冲rxbuf。
当接收到数据,根据自定义的中断方式,将置位相应的中断标志位(在读取中断标志位时会自动将其清零)
if(MCBSP_rrdy(hMcbsp)){ //DRR寄存器已存在数据
        if(frame_error){
                if(reccnt == 9){
                        frame_error = 0;
                        recchar = 0;
                        reccnt = 0;
                }
                else{
                        reccnt++;
                }
        }
        else{
                recchar = MCBSP_read16(hMcbsp);
                if(bitscan(recchar)>8){  //此位被视为1
                        switch(reccnt){
                                case 0:{  //检测起始位,这时起始位错误,发生帧错误
                                        frame_error = 1;
                                        reccnt++;
                                        break;
                                }
                                case 1: recans |= 0x0001; reccnt++;  break;
                                case 2: recans |= 0x0002; reccnt++;  break;
                                case 3: recans |= 0x0004; reccnt++;  break;
                                case 4: recans |= 0x0008; reccnt++;  break;
                                case 5: recans |= 0x0010; reccnt++;  break;
                                case 6: recans |= 0x0020; reccnt++;  break;
                                case 7: recans |= 0x0040; reccnt++;  break;
                                case 8: recans |= 0x0080; reccnt++;  break;
                                case 9:{  //检测结束位
                                        recflag = 1;  //接收正确,正确的数据将存在recchar中,如若有需要,请将数据提取到有用位置
                                        reccnt = 0;
                                        recchar = 0;
                                        frame_error = 0;
                                        recans = 0;
                                        break;
                                }
                                default: break;
                        }
                }
                else{
                        if(reccnt == 9){  //结束位出错
                                recflag = 0;
                                recchar = 0;
                                reccnt = 0;
                                recans = 0;
                                //frame_error = 0;
                        }
                        else{
                                reccnt++;
                        }
                }
        }
}
将需要发送的数据存储到rxbuf,并逐个移入发送寄存器
for(y=255; y>0; y--){
        if(sendflag){       //sendflag有数据需要发送
                char2rxbuf(y);  //数据准备
                for(i=0; i<10; i++){
                        #ifdef _USE_CSL_
                        while(!MCBSP_xrdy(hMcbsp));
                        #endif
                        #ifdef _USE_IOPORT_
                        while(SPCR2_1&0x0020);
                        #endif
                        MCBSP_write16(hMcbsp, rxbuf);
                }
                sendflag = 1;
        }
}
这里在正常发送时,先发送一帧数据,是DX将发送总线拉高,否则传输第一个字节将发生错误,一般可以发现是0x00
                               

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入30汤圆

发表于 2014-8-21 15:49:09 | 显示全部楼层
顶你。最近用到5509A,不得不说,这个MCBSP真是绕。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-3-29 03:39

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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