1. 问题:C6713B作为从机,通过McBSP与STM32F407进行SPI通信,C6713B在接收SPI数据时,McBSP的rrdy(SPCR)不会自动置1。通过示波器查看,STM32发出的时钟和数据都是正常的。
2. 原理图设计:
(1)DSP端接口
(2)STM32端接口
其中PA5,PA6接口复用了(测试时STM32只有SPI程序)
3. 程序
(1)C6713B程序
配置McBSP
void ConfigMcbsp(MCBSP_Handle *hMcbsp_ch0) {
*hMcbsp_ch0 = MCBSP_open(MCBSP_DEV1, MCBSP_OPEN_RESET);
/* create a config structure for digital SPI slave mode */
static MCBSP_Config ConfigSPISlave = {
MCBSP_SPCR_RMK(
MCBSP_SPCR_FREE_YES,
MCBSP_SPCR_SOFT_YES,
MCBSP_SPCR_FRST_YES
MCBSP_SPCR_GRST_YES,
MCBSP_SPCR_XINTM_XRDY,
MCBSP_SPCR_XSYNCERR_NO,
MCBSP_SPCR_XRST_YES,
MCBSP_SPCR_DLB_OFF,
MCBSP_SPCR_RJUST_RZF,
MCBSP_SPCR_CLKSTP_NODELAY,
MCBSP_SPCR_DXENA_OFF,
MCBSP_SPCR_RINTM_RRDY,
MCBSP_SPCR_RSYNCERR_NO,
MCBSP_SPCR_RRST_YES
),
/* Receive Control Register (RCR) */
MCBSP_RCR_RMK(
MCBSP_RCR_RPHASE_SINGLE,
MCBSP_RCR_RFRLEN2_OF(0),
MCBSP_RCR_RWDLEN2_16BIT,
MCBSP_RCR_RCOMPAND_MSB,
MCBSP_RCR_RFIG_NO,
MCBSP_RCR_RDATDLY_0BIT,
MCBSP_RCR_RFRLEN1_OF(0),
MCBSP_RCR_RWDLEN1_16BIT,
MCBSP_RCR_RWDREVRS_DISABLE
),
/* Transmit Control Register (XCR) */
MCBSP_XCR_RMK(
MCBSP_XCR_XPHASE_SINGLE,
MCBSP_XCR_XFRLEN2_OF(0),
MCBSP_XCR_XWDLEN2_8BIT,
MCBSP_XCR_XCOMPAND_MSB,
MCBSP_XCR_XFIG_YES,
MCBSP_XCR_XDATDLY_0BIT,
MCBSP_XCR_XFRLEN1_OF(0),
MCBSP_XCR_XWDLEN1_32BIT,
MCBSP_XCR_XWDREVRS_DISABLE
),
/*serial port sample rate generator register(SRGR) */
MCBSP_SRGR_RMK(
MCBSP_SRGR_GSYNC_FREE,
MCBSP_SRGR_CLKSP_RISING,
MCBSP_SRGR_CLKSM_INTERNAL,
MCBSP_SRGR_FSGM_DXR2XSR,
MCBSP_SRGR_FPER_OF(0),
MCBSP_SRGR_FWID_OF(0),
MCBSP_SRGR_CLKGDV_OF(1)
),
MCBSP_MCR_DEFAULT,
MCBSP_RCER_DEFAULT,
MCBSP_XCER_DEFAULT,
/* serial port pin control register(PCR) */
MCBSP_PCR_RMK(
MCBSP_PCR_XIOEN_SP,
MCBSP_PCR_RIOEN_SP,
MCBSP_PCR_FSXM_EXTERNAL,
MCBSP_PCR_FSRM_EXTERNAL,
MCBSP_PCR_CLKXM_INPUT,
MCBSP_PCR_CLKRM_INPUT,
MCBSP_PCR_CLKSSTAT_0,
MCBSP_PCR_DXSTAT_0,
MCBSP_PCR_FSXP_ACTIVELOW,
MCBSP_PCR_FSRP_ACTIVELOW,
MCBSP_PCR_CLKXP_FALLING,
MCBSP_PCR_CLKRP_FALLING
)
};
MCBSP_config(*hMcbsp_ch0, &ConfigSPISlave);
}
/* —————————————————————————*/
void StartMcbsp(MCBSP_Handle *hMcbsp_ch0) {
int i;
MCBSP_enableSrgr(*hMcbsp_ch0);
for(i = 5; i > 0; i–);
MCBSP_enableFsync(*hMcbsp_ch0);
MCBSP_enableRcv(*hMcbsp_ch0);
MCBSP_enableXmt(*hMcbsp_ch0);
for(i = 5; i > 0; i–);
}
Main()函数
void main() {
int i;
CSL_init();
ConfigMcbsp(&hMcbsp_ch0);
IRQ_setVecs(vectors);
IRQ_globalEnable();
IRQ_nmiEnable();
for(i = 0; i < 32; i++) {
IRQ_disable(i);
IRQ_clear(i);
}
IRQ_map(IRQ_EVT_RINT1, 4);
IRQ_reset(IRQ_EVT_RINT1);
IRQ_enable(IRQ_EVT_RINT1);
StartMcbsp(&hMcbsp_ch0);
MCBSP_write(hMcbsp_ch0, 0x0000e40a);
while(!MCBSP_rrdy(hMcbsp_ch0));
data = MCBSP_read(hMcbsp_ch0);
while(1) {
}
}
中断函数
interrupt void SPIEventIsr(void) {
data = MCBSP_read(hMcbsp_ch0);
}
中断向量配置
*——————————————————————————
* Global symbols defined here and exported out of this file
*——————————————————————————
.global _vectors
.global _c_int00
.global _vector1
.global _vector2
.global _vector3
.global _SPIEventIsr ; Hookup the SPI ISR in main()
.global _vector5
.global _vector6
.global _vector7
.global _vector8
.global _vector9
.global _vector10
.global _vector11
.global _vector12
.global _vector13
.global _vector14
.global _vector15
*——————————————————————————
* This is the actual interrupt service table (IST). It is properly aligned and
* is located in the subsection .text:vecs. This means if you don't explicitly
* specify this section in your linker command file, it will default and link
* into the .text section. Remember to set the ISTP register to point to this
* table.
*——————————————————————————
.sect ".text:vecs"
.align 1024
_vectors:
_vector0: VEC_ENTRY _c_int00 ;RESET
_vector1: VEC_ENTRY _vec_dummy ;NMI
_vector2: VEC_ENTRY _vec_dummy ;RSVD
_vector3: VEC_ENTRY _vec_dummy
_vector4: VEC_ENTRY _SPIEventIsr
_vector5: VEC_ENTRY _vec_dummy
_vector6: VEC_ENTRY _vec_dummy
_vector7: VEC_ENTRY _vec_dummy
_vector8: VEC_ENTRY _vec_dummy
_vector9: VEC_ENTRY _vec_dummy
_vector10: VEC_ENTRY _vec_dummy
_vector11: VEC_ENTRY _vec_dummy
_vector12: VEC_ENTRY _vec_dummy
_vector13: VEC_ENTRY _vec_dummy
_vector14: VEC_ENTRY _vec_dummy
_vector15: VEC_ENTRY _vec_dummy
(2)STM32程序
SPI配置
void SPI1_Init(void) {
GPIO_InitTypeDef GPIO_InitStructure;
SPI_InitTypeDef SPI_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //复用功能
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_ResetBits(GPIOA, GPIO_Pin_4);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_SPI1); //PA5复用为SPI1
GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_SPI1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_SPI1);
RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1, ENABLE); //复位SPI1
RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1, DISABLE); //停止复位SPI1
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //设置双向模式
SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //SPI主模式
SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b; //16位帧结构
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; //时钟极性
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; //时钟相位
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS信号由SSI位控制
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; //256分频
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //数据位从MSB位开始
SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC值计算的多项式
SPI_Init(SPI1, &SPI_InitStructure);
SPI_Cmd(SPI1, ENABLE); //使能SPI外设
SPI1_ReadWriteByte(0xffff); //启动传输
}
u16 SPI1_ReadWriteByte(u16 txdata) {
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET) {} //等待发送区空
SPI_I2S_SendData(SPI1, txdata);
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET) {} //等待接收完一个byte
return SPI_I2S_ReceiveData(SPI1); //返回SPI1最近接收到的数据
}
Main()函数
int main() {
u8 i;
volatile u16 high16bits = 0;
volatile u16 low16bits = 0;
volatile u16 temp;
SPI1_Init();
DelayInit();
for(i = 0; i < RXDATA_SIZE; i++) xdata[i] = i;
Delayms(500);
while(1) {
for(i = 0; i < RXDATA_SIZE; i++) { //每次发32个数据
Delayus(4);
GPIO_SetBits(GPIOA, GPIO_Pin_4);
Delayus(4);
GPIO_ResetBits(GPIOA, GPIO_Pin_4);
Delayus(4);
high16bits = SPI1_ReadWriteByte(xdata[i]) ;
}
}
}
麻烦老师帮忙看一下问题,如有结果烦请尽快告知,谢谢!第一次发帖求助,如有不规范的地方还请多多指教。
ming xiao:
可以试试加一个延时