专家
公告
财富商城
电子网
旗下网站
首页
问题库
专栏
标签库
话题
专家
NEW
门户
发布
提问题
发文章
TI
MSP430的SPI协议分析和简单实例
2019-07-23 16:01
发布
×
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮
站内问答
/
TI MCU
2115
5
1559
MSP430的SPI协议分析和简单实例
友情提示:
此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
5条回答
yiyigirl2014
2019-07-24 02:50
初始化函数:SpiMasterInit,实现主机模式的初始化工作,函数内容如下:
char SpiMasterInit(long baud,char dataBits,char mode,char clkMode)
{
long int brclk; //波特率发生器时钟频率
UxCTL |= SWRST; //初始
//反馈选择位,为1,发送的数被自己接收,用于测试,正常使用时注释掉
//UxCTL |= LISTEN;
UxCTL |= SYNC + MM; //SPI 主机模式
//时钟源设置
UxTCTL &=~ (SSEL0+SSEL1); //清除之前的时钟设置
if(baud<=16364) //
{
UxTCTL |= SSEL0; //ACLK,降低功耗
brclk = 32768; //波特率发生器时钟频率=ACLK(32768)
}
else
{
UxTCTL |= SSEL1; //SMCLK,保证速度
brclk = 1000000; //波特率发生器时钟频率=SMCLK(1MHz)
}
//------------------------设置波特率-------------------------
if(baud < 300||baud > 115200) //波特率超出范围
{
return 0;
}
//设置波特率寄存器
int fen = brclk / baud; //分频系数
if(fen<2)return (0); //分频系数必须大于2
else
{
UxBR0 = fen / 256;
UxBR1 = fen % 256;
}
//------------------------设置数据位-------------------------
switch(dataBits)
{
case 7:case'7': UxCTL &=~ CHAR; break; //7位数据
case 8:case'8': UxCTL |= CHAR; break; //8位数据
default : return(0); //参数错误
}
//------------------------设置模式---------------------------
switch(mode)
{
case 3:case'3': UxTCTL |= STC; USPI3ON; break; //三线模式
case 4:case'4': UxTCTL &=~ STC; USPI4ON; break; //四线模式
default : return(0); //参数错误
}
//------------------------设置UCLK模式-----------------------
switch(clkMode)
{
case 0:case'0': UxTCTL &=~ CKPH; UxTCTL &=~ CKPL; break; //模式0
case 1:case'1': UxTCTL &=~ CKPH; UxTCTL |= CKPL; break; //模式1
case 2:case'2': UxTCTL |= CKPH; UxTCTL &=~ CKPL; break; //模式2
case 3:case'3': UxTCTL |= CKPH; UxTCTL |= CKPL; break; //模式3
default : return(0); //参数错误
}
UxME |= USPIEx; //模块使能
UCTL0 &= ~SWRST; // Initialize USART state machine
UxIE |= URXIEx + UTXIEx; // Enable USART0 RX interrupt
return(1); //设置成功
}
程序注释已经比较详细,这里不再细说;如果要改为从机模式,把时钟设置和波特率设置去掉应该就可以了。
发送函数和接收函数:
void SpiWriteDat(char c)
{
while (TxFlag==0) SpiLpm(); // 等待上一字节发完,并休眠
TxFlag=0; //
UxTXBUF=c;
}
char SpiReadDat()
{
while (RxFlag==0) SpiLpm(); // 收到一字节?
RxFlag=0;
return(UxRXBUF);
}
发送和接收函数和异步通信里面的几乎一样,如果标志位为0,则等待改变为1,然后写入或读出;标志位在中断函数里被更改;中断函数如下:
#pragma vector=USARTxRX_VECTOR
__interrupt void UartRx()
{
RxFlag=1;
__low_power_mode_off_on_exit();
}
#pragma vector=USARTxTX_VECTOR
__interrupt void UartTx ()
{
TxFlag=1;
__low_power_mode_off_on_exit();
}
中断里面仅仅置标志位后,就退出低功耗;退出后即写入或者读取数据。
读取或写入函数调用的SpiLpm函数:
void SpiLpm()
{
if(UxTCTL&SSEL0) LPM3; //若以ACLK 作时钟,进入LPM3休眠(仅打开ACLK)
else LPM0; //若以SMCLK作时钟,进入LPM0休眠(不关闭SMCLK)
}
根据不同情况进入低功耗,如果单片机其他地方不允许进入低功耗,可以更改这个函数。
程序部分就这么多了。需要的函数在头文件里面声明,方便使用。
3.使用示例:
程序使用方式和之前的程序库相同,加入c文件,包含h文件,调用初始化函数后即可掉用程序库中的函数。
#include "msp430x16x.h" //430寄存器头文件
#include "Spi.h" //串口通讯程序库头文件
void main()
{
// Stop watchdog timer to prevent time out reset
WDTCTL = WDTPW + WDTHOLD;
ClkInit();
// 主机模式,波特率25000,8位数据位,三线模式,时钟模式0(具体见spi.c)
SpiMasterInit(25000,8,3,0);
_EINT();
while(1) //串口测试
{
SpiWriteDat(0X20);
char a = SpiReadDat();
}
}
这里只是一个简单的使用示例,详细的使用,将会在下一篇给出,下一篇:MSP430程序库<六>通过SPI操作AD7708;将会使用今天的程序库,完成SPI的通信部分。
4.注意事项:
SPI是全双工通信,每次写入(发送)8位/7位数据的同时,430的SPI主模块都会在发送后半个时钟周期读取采样的0/1信号,存入接收缓冲寄存器,所以,每次的写入,均有数据读取,但不一定是从设备发送回来的,这个地方在使用430主机模式的时候必须注意,很容易出错(我也是在调试AD7708的时候才注意到这个地方的);SPI的函数已经添加SpiWriteData函数,这个函数会在发送的同时返回发送完成半个时钟周期后的接收到的数据,方便使用;不建议使用前面的发送和读取函数,很容易出错;建议使用刚添加的这个函数,程序库已经更新,可以重新下载。函数SpiWriteData:
char SpiWriteData(char c)
{
SpiWriteDat(c);
return SpiReadDat();
}
发送后读取即可,程序比较简单。
新的示例程序:
void main()
{
// Stop watchdog timer to prevent time out reset
WDTCTL = WDTPW + WDTHOLD;
ClkInit();
// 主机模式,波特率25000,8位数据位,三线模式,时钟模式0(具体见spi.c)
SpiMasterInit(25000,8,3,0);
_EINT();
while(1) //串口测试
{
SpiWriteData(0X20); //只写入
char a = SpiWriteData(0xff); //只读取
}
}
加载中...
查看其它5个回答
一周热门
更多
>
相关问题
CPLD的方波输出
4 个回答
11个版本Quartus II 软件下载,安装包网盘合集,附教程,47G!
20 个回答
请大家帮忙到21IC发展大家谈支持我申请新版面
20 个回答
【通知】21ic中国电子网服务条款 (所有人员必读)
1 个回答
满载而归乙亥年,大展鸿途庚子年---集签赢好礼
20 个回答
相关文章
×
关闭
采纳回答
向帮助了您的知道网友说句感谢的话吧!
非常感谢!
确 认
×
关闭
编辑标签
最多设置5个标签!
TI
保存
关闭
×
关闭
举报内容
检举类型
检举内容
检举用户
检举原因
广告推广
恶意灌水
回答内容与提问无关
抄袭答案
其他
检举说明(必填)
提交
关闭
×
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮
×
付费偷看金额在0.1-10元之间
确定
×
关闭
您已邀请
0
人回答
查看邀请
擅长该话题的人
回答过该话题的人
我关注的人
初始化函数:SpiMasterInit,实现主机模式的初始化工作,函数内容如下:
char SpiMasterInit(long baud,char dataBits,char mode,char clkMode)
{
long int brclk; //波特率发生器时钟频率
UxCTL |= SWRST; //初始
//反馈选择位,为1,发送的数被自己接收,用于测试,正常使用时注释掉
//UxCTL |= LISTEN;
UxCTL |= SYNC + MM; //SPI 主机模式
//时钟源设置
UxTCTL &=~ (SSEL0+SSEL1); //清除之前的时钟设置
if(baud<=16364) //
{
UxTCTL |= SSEL0; //ACLK,降低功耗
brclk = 32768; //波特率发生器时钟频率=ACLK(32768)
}
else
{
UxTCTL |= SSEL1; //SMCLK,保证速度
brclk = 1000000; //波特率发生器时钟频率=SMCLK(1MHz)
}
//------------------------设置波特率-------------------------
if(baud < 300||baud > 115200) //波特率超出范围
{
return 0;
}
//设置波特率寄存器
int fen = brclk / baud; //分频系数
if(fen<2)return (0); //分频系数必须大于2
else
{
UxBR0 = fen / 256;
UxBR1 = fen % 256;
}
//------------------------设置数据位-------------------------
switch(dataBits)
{
case 7:case'7': UxCTL &=~ CHAR; break; //7位数据
case 8:case'8': UxCTL |= CHAR; break; //8位数据
default : return(0); //参数错误
}
//------------------------设置模式---------------------------
switch(mode)
{
case 3:case'3': UxTCTL |= STC; USPI3ON; break; //三线模式
case 4:case'4': UxTCTL &=~ STC; USPI4ON; break; //四线模式
default : return(0); //参数错误
}
//------------------------设置UCLK模式-----------------------
switch(clkMode)
{
case 0:case'0': UxTCTL &=~ CKPH; UxTCTL &=~ CKPL; break; //模式0
case 1:case'1': UxTCTL &=~ CKPH; UxTCTL |= CKPL; break; //模式1
case 2:case'2': UxTCTL |= CKPH; UxTCTL &=~ CKPL; break; //模式2
case 3:case'3': UxTCTL |= CKPH; UxTCTL |= CKPL; break; //模式3
default : return(0); //参数错误
}
UxME |= USPIEx; //模块使能
UCTL0 &= ~SWRST; // Initialize USART state machine
UxIE |= URXIEx + UTXIEx; // Enable USART0 RX interrupt
return(1); //设置成功
}
程序注释已经比较详细,这里不再细说;如果要改为从机模式,把时钟设置和波特率设置去掉应该就可以了。
发送函数和接收函数:
void SpiWriteDat(char c)
{
while (TxFlag==0) SpiLpm(); // 等待上一字节发完,并休眠
TxFlag=0; //
UxTXBUF=c;
}
char SpiReadDat()
{
while (RxFlag==0) SpiLpm(); // 收到一字节?
RxFlag=0;
return(UxRXBUF);
}
发送和接收函数和异步通信里面的几乎一样,如果标志位为0,则等待改变为1,然后写入或读出;标志位在中断函数里被更改;中断函数如下:
#pragma vector=USARTxRX_VECTOR
__interrupt void UartRx()
{
RxFlag=1;
__low_power_mode_off_on_exit();
}
#pragma vector=USARTxTX_VECTOR
__interrupt void UartTx ()
{
TxFlag=1;
__low_power_mode_off_on_exit();
}
中断里面仅仅置标志位后,就退出低功耗;退出后即写入或者读取数据。
读取或写入函数调用的SpiLpm函数:
void SpiLpm()
{
if(UxTCTL&SSEL0) LPM3; //若以ACLK 作时钟,进入LPM3休眠(仅打开ACLK)
else LPM0; //若以SMCLK作时钟,进入LPM0休眠(不关闭SMCLK)
}
根据不同情况进入低功耗,如果单片机其他地方不允许进入低功耗,可以更改这个函数。
程序部分就这么多了。需要的函数在头文件里面声明,方便使用。
3.使用示例:
程序使用方式和之前的程序库相同,加入c文件,包含h文件,调用初始化函数后即可掉用程序库中的函数。
#include "msp430x16x.h" //430寄存器头文件
#include "Spi.h" //串口通讯程序库头文件
void main()
{
// Stop watchdog timer to prevent time out reset
WDTCTL = WDTPW + WDTHOLD;
ClkInit();
// 主机模式,波特率25000,8位数据位,三线模式,时钟模式0(具体见spi.c)
SpiMasterInit(25000,8,3,0);
_EINT();
while(1) //串口测试
{
SpiWriteDat(0X20);
char a = SpiReadDat();
}
}
这里只是一个简单的使用示例,详细的使用,将会在下一篇给出,下一篇:MSP430程序库<六>通过SPI操作AD7708;将会使用今天的程序库,完成SPI的通信部分。
4.注意事项:
SPI是全双工通信,每次写入(发送)8位/7位数据的同时,430的SPI主模块都会在发送后半个时钟周期读取采样的0/1信号,存入接收缓冲寄存器,所以,每次的写入,均有数据读取,但不一定是从设备发送回来的,这个地方在使用430主机模式的时候必须注意,很容易出错(我也是在调试AD7708的时候才注意到这个地方的);SPI的函数已经添加SpiWriteData函数,这个函数会在发送的同时返回发送完成半个时钟周期后的接收到的数据,方便使用;不建议使用前面的发送和读取函数,很容易出错;建议使用刚添加的这个函数,程序库已经更新,可以重新下载。函数SpiWriteData:
char SpiWriteData(char c)
{
SpiWriteDat(c);
return SpiReadDat();
}
发送后读取即可,程序比较简单。
新的示例程序:
void main()
{
// Stop watchdog timer to prevent time out reset
WDTCTL = WDTPW + WDTHOLD;
ClkInit();
// 主机模式,波特率25000,8位数据位,三线模式,时钟模式0(具体见spi.c)
SpiMasterInit(25000,8,3,0);
_EINT();
while(1) //串口测试
{
SpiWriteData(0X20); //只写入
char a = SpiWriteData(0xff); //只读取
}
}
一周热门 更多>