本帖最后由 xxguo 于 2012-10-2 20:50 编辑
现有STC12C5616和CC2530两个单片机。需要两个单片机SPI通信(5616为master,2530为slaver),请问现在有哪些需要注意的问题呢?
我已经实现5616和5616之间的SPI以及2530与2530之间的SPI通信。但是交叉之后就是没有反应,不知道可能是哪里的问题呢?
/*******************************************************************************
date : 2010/08/29
writer :on the way..
Port :P0_2,P0_3,P0_4,P0_5 这四个端口是用于UART0外设配置
P1_0,P1_1 这两个端口是LED1和LED2
P1_4,P1_5,P1_6,P1_7 这四个端口用于SPI通信
fuction:SPI_DMA中断方式通信
从模式:配置好DMA的参数,使能DMA中断之后,开启DMA,如
果串口1有接收到数据,这是会触发DMA,传输数据到指定的数组
rxBufferSlave中,这里是可以将整个字符串直接传送过来的,最
后在串口调试助手中显示on the way..
*******************************************************************************/
/*--------------------------------------------------------------------------------
Master Slave
------------- -------------
| | | |
|P1_4 SSN |--------->|SSN P1_4|
| | | |
|P1_5 SCK |--------->|SCK P1_5|
| | | |
|P1_6 MOSI|--------->|MOSI P1_6|
| | | |
|P1_7 MISO|<---------|MISO P1_7|
| | | |
------------- -------------
--------------------------------------------------------------------------------*/
// Slave Mode
#include <iocc2530.h>
#include "hal_cc8051.h"
#define LED1 P1_0
#define LED2 P1_1
#define LED_OFF 1
#define LED_ON 0
#define SSN P1_4
#define N 13 // Length byte
char rxBufferSlave[13];//接收到的数据放到这个数组中
BOOL sDataReceived; //接收数据标志位
/******************************************************************************
* @fn init_port
*
* @brief
* Initializes components IO port application example.
*
* Parameters:
*
* @param void
*
* @return void
*
******************************************************************************/
void init_port(void)
{
IO_FUNC_PORT_PIN(1, 0, IO_FUNC_GIO); //将P1_0设置为普通的IO口
IO_DIR_PORT_PIN(1, 0, IO_OUT); //设置为输出
IO_FUNC_PORT_PIN(1, 1, IO_FUNC_GIO); //将P1_1设置为普通的IO口
IO_DIR_PORT_PIN(1, 1, IO_OUT); //设置为输出
PERCFG |= 0x02; // PERCFG.U1CFG = 1
P1SEL |= 0xF0; // P1_7, P1_6, P1_5, and P1_4 are peripherals
}
void init_Baudrate(void)
{
// a 32 MHz crystal,
// max baud rate = 32 MHz / 8 = 4 MHz.
U1BAUD = 0x00; // BAUD_M = 0
U1GCR |= 0x11; // BAUD_E = 17
}
/******************************************************************************
* @fn initUART
*
* @brief
* Initializes components for the UART application example.
*
* Parameters:
*
* @param void
*
* @return void
*
******************************************************************************/
void initUART(void)
{
// Setup for UART0
IO_PER_LOC_UART0_AT_PORT0_PIN2345();//将端口0的2345设置为外设
//这里的串口0设置为:波特率57600,没有校验位,8位数据,1位停止位,
UART_SETUP(0, 57600, HIGH_STOP); //设置串口
}
/*******************************************************************************
* @fn main
*
* @brief
*
* @param none
*
* @return none
*******************************************************************************/
void main(void)
{
uint8 i;
halMcuInit(); //设置时钟源32MHZ
init_port(); //初始化端口
init_Baudrate(); //初始化波特率
initUART(); //初始化UART
// SPI Slave Mode
U1CSR &= ~0x80;
U1CSR |= 0x20;
// Configure phase, polarity, and bit order
U1GCR |= 0xC0; // CPOL = CPHA = 1
U1GCR &=~0x20; // ORDER = 1
// 1. Clear interrupt flags
// For pulsed or edge shaped interrupt sources one should clear the CPU interrupt
// flag prior to clearing the module interrupt flag
TCON &= ~0x80;
// 2. Set individual interrupt enable bit in the peripherals SFR, if any
// 3. Set the corresponding individual, interrupt enable bit in the IEN0, IEN1, or
// IEN2 registers to 1
URX1IE = 1;
// SPI Slave
//-------------------------------------------------------------------------------
DMA_DESC dmaConfigRx;
SET_WORD(dmaConfigRx.SRCADDRH, dmaConfigRx.SRCADDRL, &X_U1DBUF);
SET_WORD(dmaConfigRx.DESTADDRH, dmaConfigRx.DESTADDRL, rxBufferSlave);
dmaConfigRx.VLEN = 0; // Transfer number of bytes commanded by n, + 1
SET_WORD(dmaConfigRx.LENH, dmaConfigRx.LENL, N + 1); //LEN = nmax + 1
dmaConfigRx.WORDSIZE = 0; // Each transfer is 8 bits
dmaConfigRx.TRIG = 17; // Use URX1 trigger 17
dmaConfigRx.TMODE = 0; // One byte transferred per trigger event 0
dmaConfigRx.SRCINC = 1; // Keep the same source addr. for all transfers 0
dmaConfigRx.DESTINC = 0; // Increase dest. addr. by 1 between transfers 1
dmaConfigRx.IRQMASK = 1; // Allow IRCON.DMAIF to be asserted when the transfer 1
// count is reached
dmaConfigRx.M8 = 0; // Use all 8 bits of first byte in source data to
// determine the transfer count
dmaConfigRx.PRIORITY = 2; // DMA memory access has high priority
// Save pointer to the DMA config. struct into DMA ch. 0 config. registers
SET_WORD(DMA0CFGH, DMA0CFGL, &dmaConfigRx);
//-------------------------------------------------------------------------------
//-------------------------------------------------------------------------------
// 1. Clear interrupt flags
// For pulsed or edge shaped interrupt sources one should clear the CPU interrupt
// flag prior to clearing the module interrupt flag
DMAIF = 0; //清除DMA中断标志位
DMAIRQ &= ~0x01;
// 2. Set individual interrupt enable bit in the peripherals SFR, if any
// No flag for the DMA (Set in the DMA struct (IRQMASK = 1))
// 3. Set the corresponding individual, interrupt enable bit in the IEN0, IEN1, o
// IEN2 registers to 1
DMAIE = 1; //使能DMA中断
// 4. Enable global interrupt
EA = 1; //使能总中断
//-------------------------------------------------------------------------------
//-------------------------------------------------------------------------------
DMAARM = 0x01; //使得DMA通道0处于准备好的状态,如果有数据接收到,就会执行中断语句
while (1)
{
if (sDataReceived)
{
sDataReceived = FALSE; // All 10 bytes are received
for(i=0;i<sizeof(rxBufferSlave)+1;i++)
{
U0DBUF = rxBufferSlave;
while(UTX0IF == 0); //等待发送完毕
UTX0IF = 0;
}
}
}
}
#pragma vector=DMA_VECTOR
__interrupt void dma_IRQ(void)
{
DMAIF = 0; // Clear the CPU DMA interrupt flag
DMAIRQ &= ~0x01; // DMA channel 0 module interrupt flag
sDataReceived = TRUE; // All 10 bytes are received
}
//-------------------------------------------------------------------------------
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
一个是5v的一个是3.3V的,非要加那个吗?
功能 : STC12C5616 与 CC2530 单片机之间进行SPI通信,交换部分数据。
从串口调试助手把一个八位的数据 发到Master上,Master接收到数据之后,通过SPI把数据发送给Slaver。与此同时Slaver直接又把另一组数据转发给Master,然后Master把接收到的数据发给上位机。然后Slaver把从Master那里接受来的数据发送到另一个串口调试助手!
Master : STC12C5616
Slaver : CC2530
连接:
Master Slave
-----------------------------------------------------
| | | |
|P1_4 SSN |--------->| SSN P1_4 |
| | | |
|P1_7 SCK |--------->| SCK P1_5 |
| | | |
|P1_5 MOSI |--------->| MOSI P1_6 |
| | | |
|P1_6 MISO |<---------| MISO P1_7 |
| | | |
-----------------------------------------------------
注意事项:虽然两种单片机之间的逻辑电平不一致,但是5V的作为主机,3.3V的作为从机,并不影响,依然可以正常通信。
但是记得,两个单片机之间要公地!!!
Master 依然不变
#include "reg51.h"
#define SPIF ( SPSTAT & 0x80 ) //查询SPIF是否置位,SPIF不能进行位操作
/*通信端口设置-------------------------------------------------------*/
/**********************************************************************
定义寄存器
************************************************************************/
sfr AUXR = 0x8e; //Auxiliary register
sfr SPSTAT = 0x84; //SPI status register 1000 0100
//#define SPIF 0x80 //SPSTAT.7
#define WCOL 0x40 //SPSTAT.6
sfr SPCTL = 0x85; //SPI control register 1000 0101 master SPI禁止 MSB先发 主模式 。。。16分频
#define SSIG 0x80 //SPCTL.7
#define SPEN 0x40 //SPCTL.6
#define DORD 0x20 //SPCTL.5
#define MSTR 0x10 //SPCTL.4
#define CPOL 0x08 //SPCTL.3
#define CPHA 0x04 //SPCTL.2
#define SPDHH 0x00 //CPU_CLK/4
#define SPDH 0x01 //CPU_CLK/16
#define SPDL 0x02 //CPU_CLK/64
#define SPDLL 0x03 //CPU_CLK/128
sfr SPDAT = 0x86; //SPI data register
/////////////////////////////////////////////////////////////////////
sbit SCLK = P1^7;
sbit MISO = P1^6;
sbit MOSI = P1^5;
sbit SS = P1^4;
unsigned char UART_SendData=0;
unsigned char UART_RecData=0;
unsigned char SPI_RecData=0;
void Init_System();
void Init_UART();
void Init_SPI();
unsigned char SPI_SendByte(unsigned char SPI_SendData);
void UART_SendByte(unsigned char UART_Send);
void delay_ms(unsigned int s);
/*---------------------------------------------------------
*函数名:main
*函数功能:系统初始化
*输入参数:无
*返回参数:无
----------------------------------------------------------*/
void main()
{
Init_System();
while(1)
{
/* 查询UART接收信号 ----------------------------------*/
while(!RI); //查看串口是否接收到数据
{
RI=0; //当接收到数据后,清除接收中断标志
UART_RecData=SBUF; //读入数据
UART_SendData=SPI_SendByte(UART_RecData);//将收到的数据由SPI发送出去,又接收回来
UART_SendByte(UART_SendData);
}
}
}
/*---------------------------------------------------------
*函数名:Init_System
*函数功能:系统初始化
*输入参数:无
*返回参数:无
----------------------------------------------------------*/
void Init_System()
{
Init_UART();
Init_SPI();
}
/*---------------------------------------------------------
*函数名:Init_UART
*函数功能:串口初始化,无中断方式
*输入参数:无
*返回参数:无
----------------------------------------------------------*/
void Init_UART()
{
TMOD=0x20;//设置定时器1为工作方式2
AUXR|=0x40;//不对定时器1分频,速度是普通单片机的12倍
TH1=0xd9; //波特率为9600,晶振为12MHz
TL1=0xd9;
TR1=1; //启动T1
REN=1; //串行允许位
// PCON=0x80; //PCON寄存器的SMOD位置一,波特率提高一倍
SM0=0;
SM1=1; //串行方式1
// ES=1; //中断接收则开串口中断,查询接收则关闭此句
}
/*---------------------------------------------------------
*函数名:Init_SPI
*函数功能:SPI初始化,SPI的工作方式,不使用SPI中断方式
*输入参数:无
*返回参数:无
----------------------------------------------------------*/
void Init_SPI()
{
SPCTL = 0xff;//CPU_CLK/16,时钟前沿为下降沿,后沿采样,主模式,最低位在前,SPI使能 1111 1111
SPSTAT = 0xc0;//SPDAT.7和SPDAT.6写11,可以将中断标志清零。注意是写1才清零
}
/*---------------------------------------------------------
*函数名:SPI_SendByte
*函数功能:SPI发射接收一体程序
*输入参数:SPI_SendData,经主机发给从机的数据
*返回参数:从机发给主机的数据
----------------------------------------------------------*/
unsigned char SPI_SendByte(unsigned char SPI_SendData)
{
SS=0;
delay_ms(2);
SPDAT= SPI_SendData; //将串口接收的数据装入SPI数据寄存器
while(!SPIF);//等待发送完毕
delay_ms(2);
SS=1;
SPSTAT = 0xc0; //清除中断标志,和写冲突标志,注意是对应位写1才能清零
SPI_RecData = SPDAT;
return SPI_RecData;
}
/*---------------------------------------------------------
*函数名:UART_SendByte
*函数功能:串口发送
*输入参数:UART_Send
*返回参数:无
----------------------------------------------------------*/
void UART_SendByte(unsigned char UART_Send)
{
TI = 0; //清除发送SBUF空标志
SBUF = UART_Send; //写入SBUF
while (!TI); //等待发送完毕
TI = 0; //清除发送SBUF空标志
}
void delay_ms(unsigned int s) //static
{
unsigned int i;
for(;s*12>0;s--) //STC12C5616 需要*12
for(i=12000;i>0;i--); //STC12C5616 需要*12
}
Slaver 取消用DMA,直接用SPI收发数据就可以了~~~
// Slave Mode
#include <iocc2530.h>
#include "hal_cc8051.h"
#define LED1 P1_0
#define LED2 P1_1
#define LED_OFF 1
#define LED_ON 0
#define SSN P1_4
/******************************************************************************
* @fn init_port
*
* @brief
* Initializes components IO port application example.
*
* Parameters:
*
* @param void
*
* @return void
*
******************************************************************************/
void init_port(void)
{
IO_FUNC_PORT_PIN(1, 0, IO_FUNC_GIO); //将P1_0设置为普通的IO口
IO_DIR_PORT_PIN(1, 0, IO_OUT); //设置为输出
IO_FUNC_PORT_PIN(1, 1, IO_FUNC_GIO); //将P1_1设置为普通的IO口
IO_DIR_PORT_PIN(1, 1, IO_OUT); //设置为输出
PERCFG |= 0x02; // PERCFG.U1CFG = 1
P1SEL |= 0xF0; // P1_7, P1_6, P1_5, and P1_4 are peripherals
}
void init_Baudrate(void)
{
// Set baud rate to max (system clock frequency / 8)
// a 32 MHz crystal,
// max baud rate = 32 MHz / 8 = 4 MHz.
U1BAUD = 0x00; // BAUD_M = 0
U1GCR |= 0x11; // BAUD_E = 17
}
/******************************************************************************
* @fn initUART
*
* @brief
* Initializes components for the UART application example.
*
* Parameters:
*
* @param void
*
* @return void
*
******************************************************************************/
void initUART(void)
{
// Setup for UART0
IO_PER_LOC_UART0_AT_PORT0_PIN2345();//将端口0的2345设置为外设
//这里的串口0设置为:波特率57600,没有校验位,8位数据,1位停止位,
UART_SETUP(0, 57600, HIGH_STOP); //设置串口
}
/*******************************************************************************
* @fn main
*
* @brief
*
* @param none
*
* @return none
*******************************************************************************/
void main(void)
{
halMcuInit();// 选择32MHz晶体振荡器作为系统时钟源(主时钟源)//设置时钟源32MHZ
init_port(); //初始化端口
init_Baudrate(); //初始化波特率
initUART(); //初始化UART
// SPI Slave Mode
U1CSR &= ~0x80;
U1CSR |= 0x20;
// Configure phase, polarity, and bit order
U1GCR |= 0xC0; // CPOL = CPHA = 1
U1GCR &=~0x20; // ORDER = 0 LSB First
// LED1=LED_ON; //灯亮表示进入接收状态
char rxBufferSlave[1];
char _RSSI[1];
_RSSI[0]=0x13;
////////////////////////////////////////////////////////////////////////////////////////////////////////
// unsigned char i;
/* for (i = 0; i < sizeof(rxBufferSlave); i++)
{
while (!U1RX_BYTE);
U1RX_BYTE = 0;
rxBufferSlave = U1DBUF;
LED1=~LED1;
}
LED1=LED_OFF; //灯灭表示数据已经传送完,接着在串口上显示
for(i=0;i<sizeof(rxBufferSlave);i++)
{
U0DBUF = rxBufferSlave;
while(UTX0IF == 0); //等待发送完毕
UTX0IF = 0;
}*/
/////////////////////////////////////////////////////////////////////////////////////////////
while(1)
{
while (!U1RX_BYTE);
rxBufferSlave[0] = U1DBUF;
U1DBUF=_RSSI[0];
// U1RX_BYTE = 0;
U0DBUF = rxBufferSlave[0];
while(UTX0IF == 0); //等待发送完毕
UTX0IF = 0;
}
}
一周热门 更多>