简介
在电力电子应用中单片机经常需要和各种外围设备进行通信,本文主要介绍几种常用的通信接口的使用方法
低速时钟(LSPCLK)
c2000的一些通信接口(McBSP、SCI、SPI)是将片上的低速时钟信号作为Bitclock的,低速时钟由系统时钟分频得到,默认是四分频,如果需要修改分频系数可以使用下面这个函数
static inline void SysCtl_setLowSpeedClock(SysCtl_LSPCLKPrescaler prescaler)
串行通信接口(SCI)
SCI的发送和接收都有一个16字节的FIFO,还有一些常见的中断信号之类的,和其他串口区别不大
捏妈,API手册SCI这块直接消失了,谢谢你,TI
初始化
设置GPIO
//发送引脚
GPIO_setPadConfig(8,GPIO_PIN_TYPE_STD);
GPIO_setPinConfig(GPIO_8_SCITXDA);
GPIO_setQualificationMode(8,GPIO_QUAL_ASYNC);
//接收引脚
GPIO_setPadConfig(9,GPIO_PIN_TYPE_STD);
GPIO_setPinConfig(GPIO_9_SCIRXDA);
GPIO_setQualificationMode(9,GPIO_QUAL_ASYNC);
TI论坛上面有老哥说这个qualification不开也能用,笔者试了一下发现确实能用,按照TI的说法,这个qualification是用来防止在复杂环境下工作时受到各种噪声影响的,手册上面也让把这个打开,所以还是开了(
重置SCI
SCI_performSoftwareReset(SCIA_BASE);
设置通信速率和帧格式
波特率通过设置分频寄存器进行配置,手册给出了波特率的计算公式:
BRR = (SCIHBAUD << 8) + (SCILBAUD)
The SCI baud rate is calculated using the following equation:
SCI Asynchronous Baud = LSPCLK / ((BRR + 1) *8)最大的可设置波特率是低速时钟频率除以十六
使用Driverlib函数可以自动计算分频系数
- 帧格式需要设置数据位数、停止位数和校验方式
SCI_setConfig(SCIA_BASE,50000000,115200,//低速时钟50MHz,波特率115200
(SCI_CONFIG_WLEN_8| //8位数据位
SCI_CONFIG_STOP_ONE| //1位停止位
SCI_CONFIG_PAR_NONE)); //无校验
设置FIFO
SCI_enableFIFO(SCIA_BASE);//使能FIFO
SCI_resetTxFIFO(SCIA_BASE);//重置FIFO
SCI_resetRxFIFO(SCIA_BASE);
设置中断
下面这个是SCI的中断信号框图
初始化中断向量表(如果没有初始化的话)
Interrupt_enablePIE();
Interrupt_initModule();
Interrupt_initVectorTable();
关中断
DINT;
注册中断服务函数,函数使用的中断号可以在hw_ints.h里面找到
Interrupt_register(INT_SCIA_RX,Recv_Callback);//注册SCIA的串口接收中断服务函数
使能中断
Interrupt_enable(INT_SCIA_RX);//在CPU处使能SCIA串口接收中断
SCI_enableInterrupt(SCIA_BASE,SCI_INT_RXFF);//使能SCIA模块的接收中断
设置FIFO中断条件,接收和发送可以分别设置
SCI_setFIFOInterruptLevel(SCIA_BASE,SCI_FIFO_TX1,SCI_FIFO_RX1);
//发送和接收FIFO都在接收到一个字节之后产生中断
开中断
EINT;
其他通信外设的中断玩法和这个差不多,后面就不提了
使能SCI
SCI_enableModule(SCIA_BASE);
使用接收中断实现一个简单的echo功能
__interrupt void Recv_Callback(void)
{
uint16_t recv_buffer[1]={0};
SCI_readCharArray(SCIA_BASE,recv_buffer,1);
SCI_writeCharArray(SCIA_BASE,recv_buffer,1);
SCI_clearOverflowStatus(SCIA_BASE);
SCI_clearInterruptStatus(SCIA_BASE, SCI_INT_RXFF);
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP9);
}
集成电路总线(I2C)
初始化
设置GPIO
//SDA引脚
GPIO_setPadConfig(0,GPIO_PIN_TYPE_PULLUP);
GPIO_setPinConfig(GPIO_0_SDAA);
GPIO_setQualificationMode(0,GPIO_QUAL_ASYNC);
//SCL引脚
GPIO_setPadConfig(1,GPIO_PIN_TYPE_PULLUP);
GPIO_setPinConfig(GPIO_1_SCLA);
GPIO_setQualificationMode(1,GPIO_QUAL_ASYNC);
设置I2C
使用下面的函数进行通信速率和时钟信号占空比的设置
I2C_initController(I2CA_BASE, 200000000, 100000, I2C_DUTYCYCLE_50);
//系统时钟200MHz,通信速率100000Hz,时钟信号占空比50%
设置FIFO
I2C_enableFIFO(I2CA_BASE);
FIFO中断的设置方式和SCI是一样的
使能I2C
I2C_enableModule(I2CA_BASE);
使用I2C进行通信(主模式)
帧格式设置
I2C_setSlaveAddress(I2CA_BASE, 0x56);//设置从机地址
I2C_setBitCount(I2CA_BASE, I2C_BITCOUNT_8);//设置每帧的数据位数
I2C_setDataCount(I2CA_BASE, 1);//设置要发送或接收的帧数
开始条件和停止条件设置
I2C_sendStartCondition(I2CA_BASE);//置位开始条件位
I2C_sendStopCondition(I2CA_BASE);//置位停止条件位
发送开始条件后I2C会在总线上产生一个开始条件并且开始发送数据,之后将开始条件位清零
设置停止条件后(1)如果工作在非连续模式下,I2C每发送一帧数据计数会减小一,当数据计数为零时向总线上发送一个停止条件并且将停止条件位清零(2)如果工作在连续模式下,数据计数不起作用,当停止条件被置位后立即产生一个停止条件
注:当I2C工作在非连续模式下并且发送地址没有得到回应时,停止条件位会被直接清零,但不会在总线上产生停止条件,这会导致总线处于繁忙状态,遇到这种情况时需要再一次置位停止条件位以释放总线(手册没有提到这点,相当坑人)
工作模式设置
I2C_setConfig(I2CA_BASE, I2C_CONTROLLER_SEND_MODE);//主机发送模式
I2C_setConfig(I2CA_BASE, I2C_CONTROLLER_RECEIVE_MODE);//主机接收模式
发送和接收
void I2C_putData(uint32_t base, uint16_t data)//向发送寄存器送入一帧数据
uint16_t I2C_getData(uint32_t base)//从接收寄存器读取一帧数据
串行外设接口(SPI)
初始化
设置GPIO
GPIO_setPadConfig(58,GPIO_PIN_TYPE_PULLUP);//引脚输入时进行内部上拉
GPIO_setPadConfig(59,GPIO_PIN_TYPE_PULLUP);
GPIO_setPadConfig(60,GPIO_PIN_TYPE_PULLUP);
GPIO_setPadConfig(61,GPIO_PIN_TYPE_PULLUP);
GPIO_setPinConfig(GPIO_58_SPISIMOA);//绑定外设
GPIO_setPinConfig(GPIO_59_SPISOMIA);
GPIO_setPinConfig(GPIO_60_SPICLKA);
GPIO_setPinConfig(GPIO_61_SPISTEA);
GPIO_setQualificationMode(58,GPIO_QUAL_ASYNC);//开qualification
GPIO_setQualificationMode(59,GPIO_QUAL_ASYNC);
GPIO_setQualificationMode(60,GPIO_QUAL_ASYNC);
GPIO_setQualificationMode(61,GPIO_QUAL_ASYNC);
设置SPI
使用下面的函数对协议格式,工作模式等进行设置
SPI_setConfig(SPIA_BASE, 50000000, SPI_PROT_POL0PHA0, SPI_MODE_CONTROLLER, 100000, 8);
//低速时钟50MHz,使用0型协议,主模式,通信速率100000Hz,一帧8位
设置FIFO
SPI_enableFIFO(SPIA_BASE);//使能FIFO
SPI_resetTxFIFO(SPIA_BASE);//重置FIFO
SPI_resetRxFIFO(SPIA_BASE);
使能SPI
SPI_enableModule(SPIA_BASE);
使用SPI进行通信
使能/禁用发送
SPI_enableTalk(SPIA_BASE);
SPI_disableTalk(SPIA_BASE);
发送
SPI_transmitByte(base, txData)//发送一个字节
SPI_transmit16Bits(base, txData)//发送一帧16bit数据
SPI_transmitNBytes(base, txBuffer, numOfWords, txDelay)//发送N个字节
void SPI_writeDataBlockingNonFIFO(uint32_t base, uint16_t data)//等待发送缓冲非满并送入一帧
void SPI_writeDataBlockingFIFO(uint32_t base, uint16_t data)//等待发送FIFO非满并送入一帧
注意:使用最下面两个函数的时候要事先对发送数据进行左对齐,在一帧有N位的情况下,data的低16-N位会被丢弃
接收
SPI_receiveByte(base, dummyData)//接收一个字节
SPI_receiveNBytes(base, rxBuffer, numOfWords, txDelay)//接收N个字节
uint16_t SPI_readDataBlockingNonFIFO(uint32_t base)//等待接收缓冲非空并接收一帧
uint16_t SPI_readDataBlockingFIFO(uint32_t base)//等待接收FIFO非空并接收一帧