大侠们,在下第一次使用msp430FR56系例单片机,在spi使用方面遇到点问题。哪位方便帮忙看下,谢谢!
这里使用的是 eUSCI_B口,主模式,数据格式8位MSB传输,时钟信号上升沿采样传递数据。3根线传输数据不使用SET引脚。spi的时钟源来自于SMCK频率1Mhz。
P1.6
P1.7
P2.2
P3.0
这个是系统时钟初始化代码
WDTCTL = WDTPW | WDTHOLD; // Stop WDT
PJSEL0 |= BIT4 + BIT5;
CSCTL0_H = 0xA5;
CSCTL1 |= DCOFSEL_6; // Set max. DCO setting
CSCTL2 = SELA_0 + SELS_3 + SELM_3; // set ACLK = XT1; MCLK = DCO
CSCTL3 = DIVA_0 + DIVS_1 + DIVM_1; // set all dividers
CSCTL4 |= LFXTDRIVE_0;
CSCTL4 &= ~LFXTOFF;
do
{
CSCTL5 &= ~LFXTOFFG;
// Clear XT1 fault flag
SFRIFG1 &= ~OFIFG;
}while (SFRIFG1&OFIFG); // Test oscillator fault flag
这是SPI初始化函数
uint8_t System_Spi_B_Init(void)
{
UCB0CTLW0 |= UCSWRST; // **Put state machine in reset**
UCB0CTLW0 |= UCMST; // 3-pin, 8-bit SPI master
UCB0CTLW0 |= UCSYNC; UCB0CTLW0 |= UCCKPL; // Clock polarity high, MSB
UCB0CTLW0 |= UCMSB; UCB0CTLW0 |= UCSSEL__SMCLK; UCB0BR0 = 0x02; // /2
UCB0BR1 = 0; //
UCA0MCTLW = 0; // No modulation
UCB0CTLW0 &= ~UCSWRST; // **Initialize USCI state machine**
return 0;
}
这是IO引脚功能复用初始化代码
PM5CTL0 &= ~LOCKLPM5;
//Set SPI_IF_Port
P3DIR |= BIT0;
P3REN |= BIT0;
P3OUT |= BIT0; //CS
P2SEL1 |= BIT2; //SPI_B_CLK P1SEL1 |= BIT6 + BIT7; //SPI_B_MISO\SPI_B_MOSI
#define SPI_CS_H {P3OUT|=BIT0;}
#define SPI_CS_L {P3OUT&=~BIT0}
下面是SPI功能函数
uint8_t SPI_RW(uint8_t byte)
{
uint8_t rec_val; SPI_CS_L // CS低为片选信号
UCB0TXBUF = byte; while((UCTXIFG & UCB0IFG) == 0);
while((UCRXIFG & UCB0IFG) == 0);
rec_val = UCB0RXBUF;
UCB0IFG &= ~UCRXIFG; SPI_CS_H
return rec_val;}
问题:
我在调试时发现接入从设备后,一个字节没有发完,CS片选引脚电平却自动恢复成高 大概是时钟的第四个上升沿时CS状态发生的变化 。大侠们能不能帮忙看下,附件为完整的工程。
shuguang sun:
注:
P1.6 MOSI 接设备 MOSI引脚
P1.7 MISO 接设备 MISO 引脚
P2.2 SCLK 接设备 SCLK 引脚
P3.0 CS 接设备 CS引脚
kqian0327:
你好,
看起来你用的是3线的SPI,因为你的CS信号是受你程序控制的。
如你的代码所述,
uint8_t SPI_RW(uint8_t byte){uint8_t rec_val; SPI_CS_L // CS低为片选信号UCB0TXBUF = byte; while((UCTXIFG & UCB0IFG) == 0);while((UCRXIFG & UCB0IFG) == 0);rec_val = UCB0RXBUF;UCB0IFG &= ~UCRXIFG; SPI_CS_Hreturn rec_val; }
所以你说CS信号恢复为高,是因为你程序写的有问题,和SPI无关,下面给你一个SPI例程供你参考。
/* –COPYRIGHT–,BSD_EX * Copyright (c) 2012, Texas Instruments Incorporated * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ******************************************************************************* * * MSP430 CODE EXAMPLE DISCLAIMER * * MSP430 code examples are self-contained low-level programs that typically * demonstrate a single peripheral function or device feature in a highly * concise manner. For this the code may rely on the device's power-on default * register values and settings such as the clock configuration and care must * be taken when combining code from several examples to avoid potential side * effects. Also see www.ti.com/grace for a GUI- and www.ti.com/msp430ware * for an API functional library-approach to peripheral configuration. * * –/COPYRIGHT–*///******************************************************************************// MSP430F59xx Demo – eUSCI_A0, SPI 3-Wire Master Incremented Data//// Description: SPI master talks to SPI slave using 3-wire mode. Incrementing// data is sent by the master starting at 0x01. Received data is expected to// be same as the previous transmission TXData = RXData-1.// USCI RX ISR is used to handle communication with the CPU, normally in LPM0.// ACLK = 32.768kHz, MCLK = SMCLK = DCO ~1MHz. BRCLK = ACLK/2////// MSP430FR5969// —————–// /|\ | XIN|-// | | | 32KHz Crystal// —|RST XOUT|-// | |// | P2.0|-> Data Out (UCA0SIMO)// | |// | P2.1|<- Data In (UCA0SOMI)// | |// | P1.5|-> Serial Clock Out (UCA0CLK)//// P. Thanigai// Texas Instruments Inc.// Feb 2012// Built with CCS V5.5//******************************************************************************#include <msp430.h>
volatile unsigned char RXData = 0;volatile unsigned char TXData;
int main(void){ WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
// Configure GPIO P1SEL1 |= BIT5; // USCI_A0 operation P2SEL1 |= BIT0 | BIT1; // USCI_A0 operation PJSEL0 |= BIT4 | BIT5; // For XT1
// Disable the GPIO power-on default high-impedance mode to activate // previously configured port settings PM5CTL0 &= ~LOCKLPM5;
// XT1 Setup CSCTL0_H = CSKEY >> 8; // Unlock CS registers CSCTL1 = DCOFSEL_0; // Set DCO to 1MHz CSCTL2 = SELA__LFXTCLK | SELS__DCOCLK | SELM__DCOCLK; CSCTL3 = DIVA__1 | DIVS__1 | DIVM__1; // set all dividers CSCTL4 &= ~LFXTOFF; do { CSCTL5 &= ~LFXTOFFG; // Clear XT1 fault flag SFRIFG1 &= ~OFIFG; }while (SFRIFG1&OFIFG); // Test oscillator fault flag CSCTL0_H = 0; // Lock CS registers
// Configure USCI_A0 for SPI operation UCA0CTLW0 = UCSWRST; // **Put state machine in reset** UCA0CTLW0 |= UCMST | UCSYNC | UCCKPL | UCMSB; // 3-pin, 8-bit SPI master // Clock polarity high, MSB UCA0CTLW0 |= UCSSEL__ACLK; // ACLK UCA0BR0 = 0x02; // /2 UCA0BR1 = 0; // UCA0MCTLW = 0; // No modulation UCA0CTLW0 &= ~UCSWRST; // **Initialize USCI state machine** UCA0IE |= UCRXIE; // Enable USCI_A0 RX interrupt TXData = 0x1; // Holds TX data
while(1) { UCA0IE |= UCTXIE; __bis_SR_register(LPM0_bits | GIE); // CPU off, enable interrupts __delay_cycles(2000); // Delay before next transmission TXData++; // Increment transmit data }}
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)#pragma vector=USCI_A0_VECTOR__interrupt void USCI_A0_ISR(void)#elif defined(__GNUC__)void __attribute__ ((interrupt(USCI_A0_VECTOR))) USCI_A0_ISR (void)#else#error Compiler not supported!#endif{ switch(__even_in_range(UCA0IV, USCI_SPI_UCTXIFG)) { case USCI_NONE: break; case USCI_SPI_UCRXIFG: RXData = UCA0RXBUF; UCA0IFG &= ~UCRXIFG; __bic_SR_register_on_exit(LPM0_bits); // Wake up to setup next TX break; case USCI_SPI_UCTXIFG: UCA0TXBUF = TXData; // Transmit characters UCA0IE &= ~UCTXIE; break; default: break; }}
shawn wang1:
B0的SPI的baud分频也是使用UCA0MCTLW = 0?
灰小子:
回复 shawn wang1:
上一楼的例子中用的是A0
YANG CHRN:
回复 kqian0327:
初学者,请教一下,这个程序实现是单片机使用SPI 主机模式,发数据给你自己吗?自发自收?
灰小子:
回复 YANG CHRN:
是SPI 主机模式,不是自发自收
YANG CHRN:
回复 灰小子:
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=USCI_A0_VECTOR
__interrupt void USCI_A0_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(USCI_A0_VECTOR))) USCI_A0_ISR (void)
#else
#error Compiler not supported!
#endif
{
switch(__even_in_range(UCA0IV, USCI_SPI_UCTXIFG))
{
case USCI_NONE: break;
case USCI_SPI_UCRXIFG:
RXData = UCA0RXBUF;
UCA0IFG &= ~UCRXIFG;
__bic_SR_register_on_exit(LPM0_bits); // Wake up to setup next TX
break;
case USCI_SPI_UCTXIFG:
UCA0TXBUF = TXData; // Transmit characters
UCA0IE &= ~UCTXIE;
break;
default: break;
}
}
请问,这个中断函数,没有搞明白。
这个中断服务函数为接收发的中断函数,他在什么时候会进入中断。
特别是__even_in_range(UCA0IV, USCI_SPI_UCTXIFG))没有看明白,请指教。
灰小子:
回复 YANG CHRN:
__even_in_range()是iar提供的一个函数。
在IAR提供的库函数里有以下内容:
/** Support for efficient switch:es. E.g. switch(__even_in_range(x, 10))** Note that the value must be even and in the range from 0 to* __bound, inclusive. No code will be generated that checks this.** This is typically used inside interrupt dispatch functions, to* switch on special processor registers like TAIV.*/
原型为:
unsigned short __even_in_range(unsigned short value, unsignedshort upper_limit);
功能:只能与switch 语句结合使用,判断value 是否为偶数且小于等于upper_limit。
在msp430里经常被用在多源中断的查询中,如 switch( __even_in_range(TAIV,10)
只有在TAIV的值是在0–10内的偶数时才会执行switch函数内的语句
其作用是提高switch语句的效率