博主:甜甜的大香瓜
声明:喝水不忘挖井人,转载请注明出处。
原文地址:http://blog.csdn.NET/feilusia
联系方式:[email protected]
香瓜BLE之CC2541群:127442605
香瓜BLE之CC2640群:557278427
香瓜BLE之Android群:541462902
五、注意事项
/**************************************************************************************************
Filename: main.c
Description: 裸机下的SPI从机代码
Date: 2015-06-17
Author: 甜甜的大香瓜
**************************************************************************************************/
#include
#include
//******************************************************************************
// MACROS
//******************************************************************************
//引脚 usart1 spi —— alt.2
#define SPI_CS P1_4
#define SPI_CLK P1_5
#define SPI_MOSI P1_6
#define SPI_MISO P1_7
//寄存器
#define UxCSR U1CSR
#define UxUCR U1UCR
#define UxDBUF U1DBUF
#define UxBAUD U1BAUD
#define UxGCR U1GCR
#define PxSEL P1SEL
#define HAL_UART_PERCFG_BIT 0x02 // USART1 on P1, Alt-2; so set this bit.
#define HAL_UART_PRIPO 0x40 // USART1 priority over UART0.
#define HAL_UART_Px_SEL_S 0xF0 // Peripheral I/O Select for Slave: SO/SI/CLK/CSn.
#define HAL_UART_Px_SEL_M 0xE0 // Peripheral I/O Select for Master: MI/MO/CLK.
// UxCSR - USART Control and Status Register.
#define CSR_MODE 0x80
#define CSR_RE 0x40
#define CSR_SLAVE 0x20
#define CSR_FE 0x10
#define CSR_ERR 0x08
#define CSR_RX_BYTE 0x04
#define CSR_TX_BYTE 0x02
#define CSR_ACTIVE 0x01
// UxUCR - USART UART Control Register.
#define UCR_FLUSH 0x80
#define UCR_FLOW 0x40
#define UCR_D9 0x20
#define UCR_BIT9 0x10
#define UCR_PARITY 0x08
#define UCR_SPB 0x04
#define UCR_STOP 0x02
#define UCR_START 0x01
//其他
#define uint8 unsigned char
#define uint16 unsigned short
//******************************************************************************
//name: test
//introduce: 测试
//parameter: none
//return: none
//******************************************************************************
uint8 tx_buf[256] = {0};
uint8 rx_buf[256] = {0};
uint8 tx_index = 0;
uint8 rx_index = 0;
void test_init(void)
{
uint16 i = 0;
for(i = 0; i < 256; i++)
{
tx_buf[i] = i;
}
}
void test(void)
{
UTX1IF = 0;
if(UxCSR & CSR_RX_BYTE){ //receive a byte
rx_buf[rx_index++] = UxDBUF;
UxDBUF = tx_buf[tx_index++];
}
}
//****************************************************************************
//名 称: SPI_Init()
//功 能: 无
//入口参数: 无
//出口参数: 无
//****************************************************************************
void SPI_Init(void)
{
volatile uint8 receive = 0;
PERCFG |= HAL_UART_PERCFG_BIT; // Set UART1 I/O to Alt. 2 location on P1.
PxSEL |= HAL_UART_Px_SEL_S; // SPI-Slave peripheral select.
UxCSR = CSR_SLAVE; // Mode is SPI-Slave Mode.
UxUCR = UCR_FLUSH; // Flush it.
UxGCR |= (1 << 5); // Set bit order to MSB.
//UxGCR &= ~(1 << 6); // CPHA
UxGCR |= (1 << 6); // CPHA
UxGCR |= (1 << 7); // CPOL
TCON &= ~(1 << 7); //清空usart1接收中断标志位
IEN0 |= (1 << 3); //使能usart1接收中断
IP0 &= ~(1 << 3); //设置spi的中断组为等级2
IP1 |= (1 << 3);
UxCSR |= CSR_RE; //使能
//SPI_Response_Byte(RESPONSE_RECEIVING); //将0xF4写入发送寄存器中待发送
UxDBUF = tx_buf[tx_index++];
receive = UxDBUF; //读寄存器,防止里面有残留数据
//测试!!!!!!!
test_init();
}
//****************************************************************************
//程序入口函数
//****************************************************************************
void main(void)
{
CLKCONCMD &= ~0x40; //设置系统时钟源为32MHZ晶振
while(CLKCONSTA & 0x40); //等待晶振稳定为32M
CLKCONCMD &= ~0x47; //设置系统主时钟频率为32MHZ
EA = 1;
SPI_Init(); //调用串口初始化函数
while(1);
}
//******************************************************************************
//name: SPI_Rx_ISR
//introduce: SPI接收中断函数
//parameter: none
//return: none
//******************************************************************************
#pragma vector = URX1_VECTOR
__interrupt void SPI_Rx_ISR(void)
{
test();
}
/**************************************************************************************************
Filename: spi.c
Description: spi slave driver
Date: 2015-06-17
Author: 甜甜的大香瓜
**************************************************************************************************/
//******************************************************************************
// INCLUDES
//******************************************************************************
#include
#include "spi.h"
#include "OSAL.h"
#include "hal_mcu.h"
#include
//******************************************************************************
// MACROS
//******************************************************************************
//引脚 usart1 spi —— alt.2
#define SPI_CS P1_4
#define SPI_CLK P1_5
#define SPI_MOSI P1_6
#define SPI_MISO P1_7
//寄存器
#define UxCSR U1CSR
#define UxUCR U1UCR
#define UxDBUF U1DBUF
#define UxBAUD U1BAUD
#define UxGCR U1GCR
#define PxSEL P1SEL
#define HAL_UART_PERCFG_BIT 0x02 // USART1 on P1, Alt-2; so set this bit.
#define HAL_UART_PRIPO 0x40 // USART1 priority over UART0.
#define HAL_UART_Px_SEL_S 0xF0 // Peripheral I/O Select for Slave: SO/SI/CLK/CSn.
#define HAL_UART_Px_SEL_M 0xE0 // Peripheral I/O Select for Master: MI/MO/CLK.
// UxCSR - USART Control and Status Register.
#define CSR_MODE 0x80
#define CSR_RE 0x40
#define CSR_SLAVE 0x20
#define CSR_FE 0x10
#define CSR_ERR 0x08
#define CSR_RX_BYTE 0x04
#define CSR_TX_BYTE 0x02
#define CSR_ACTIVE 0x01
// UxUCR - USART UART Control Register.
#define UCR_FLUSH 0x80
#define UCR_FLOW 0x40
#define UCR_D9 0x20
#define UCR_BIT9 0x10
#define UCR_PARITY 0x08
#define UCR_SPB 0x04
#define UCR_STOP 0x02
#define UCR_START 0x01
//其他
#define uint8 unsigned char
#define uint16 unsigned short
//协议相关
#define SPI_MAX_PACKET_LEN 39
#define SPI_MAX_DATA_LEN 35
#define SPI_SOF 0x7E // Start-of-frame delimiter for SPI transport.
#define SPI_EOF 0x7F // End-of-frame delimiter for SPI transport.
#define Head_CTRL 1
#define Head_COMMAND 0
#define Head(x) ((p_spi_protocol_data->Head >> x) & 0x01)
#define COMMAND_RF 1
#define COMMAND_BLE 0
#define SPI_LEN_INCR(LEN) st ( \
if (++(LEN) >= (SPI_MAX_DATA_LEN - 1)) \
{ \
(LEN) = 0; \
} \
)
#define DATA_RESET(); {spiRxSte = spiRxSteSOF; spiRxIndex = 0;}
//******************************************************************************
// GLOBAL VARIABLES
//******************************************************************************
//
typedef enum{
RESPONSE_RECEIVING = 0xF4, //正在接收
RESPONSE_RECEIVED = 0xF6, //接收完毕
RESPONSE_RESEND = 0xF7 //请求重发
}SPI_RESPONSE_BYTE;
//
typedef enum{
SPI_MALLOC_DATA_RIGHT,
SPI_MALLOC_DATA_ERROR,
}SPI_MALLOC_DATA_STATUS;
//协议包
typedef enum{
spiRxSteSOF,
spiRxSteLen,
spiRxSteData
} spiRxSte_t;
//SPI接收状态
typedef enum{
SPI_RxStatus_Receiving,
SPI_RxStatus_Received,
SPI_RxStatus_Right,
SPI_RxStatus_Error
} SPI_RXSTATUS;
//协议中的核心数据
typedef struct{
uint8 Length;
uint8 Head;
uint8 Sequence;
uint8 Binary[32];
}SPI_PROTOCOL_DATA;
SPI_PROTOCOL_DATA *p_spi_protocol_data;
//接收数据要的全局变量
spiRxSte_t spiRxSte = spiRxSteSOF;
uint16 spiRxFcs = 0; //校验和
uint8 spiRxIndex = 0; //指向接收核心数据缓冲区的第几位
uint8 spi_rx[SPI_MAX_PACKET_LEN] = {0}; //接收缓冲区
SPI_RXSTATUS spi_rx_status = SPI_RxStatus_Receiving;
static volatile uint8 check_time = 0; //用于计数主机发送F4的次数,如果过多就超时
//******************************************************************************
// LOCAL FUNCTIONS
//******************************************************************************
static void SPI_Response_Byte(SPI_RESPONSE_BYTE tx);
static SPI_MALLOC_DATA_STATUS SPI_Malloc_DATA(void);
static uint8 SPI_Packet_Receive(void);
static SPI_RXSTATUS SPI_Rx_Resolution(void);
static SPI_RXSTATUS SPI_Status_Judge(uint8 status);
static void SPI_Status_Deal(SPI_RXSTATUS status);
//******************************************************************************
//name: test
//introduce: 测试
//parameter: none
//return: none
//******************************************************************************
/*
volatile uint8 tx_buf[256] = {0};
volatile uint8 rx_buf[256] = {0};
volatile uint8 tx_index = 0;
volatile uint8 rx_index = 0;
*/
uint8 tx_buf[256] = {0};
uint8 rx_buf[256] = {0};
uint8 tx_index = 0;
uint8 rx_index = 0;
void test_init(void)
{
uint16 i = 0;
for(i = 0; i < 256; i++)
{
tx_buf[i] = i;
}
}
void test(void)
{
volatile uint8 aa = 0;
rx_buf[rx_index] = UxDBUF;
UxDBUF = tx_buf[tx_index];
if(rx_buf[rx_index] == tx_buf[rx_index]){
rx_index++;
tx_index++;
}
else{
aa =0x38;
}
}
//******************************************************************************
//name: SPI_Init
//introduce: SPI初始化
//parameter: none
//return: none
//******************************************************************************
void SPI_Init(void)
{
volatile uint8 receive = 0;
PERCFG |= HAL_UART_PERCFG_BIT; // Set UART1 I/O to Alt. 2 location on P1.
PxSEL |= HAL_UART_Px_SEL_S; // SPI-Slave peripheral select.
UxCSR = CSR_SLAVE; // Mode is SPI-Slave Mode.
UxUCR = UCR_FLUSH; // Flush it.
UxGCR |= (1 << 5); // Set bit order to MSB.
//UxGCR &= ~(1 << 6); // CPHA
UxGCR |= (1 << 6); // CPHA
UxGCR |= (1 << 7); // CPOL
TCON &= ~(1 << 7); //清空usart1接收中断标志位
IEN0 |= (1 << 3); //使能usart1接收中断
IP0 |= (1 << 3); //设置spi的中断组为等级3
//IP0 &= ~(1 << 3); //设置spi的中断组为等级2
IP1 |= (1 << 3);
UxCSR |= CSR_RE; //使能
receive = UxDBUF; //读寄存器,防止里面有残留数据
//UxDBUF = tx_buf[tx_index++];
SPI_Response_Byte(RESPONSE_RECEIVING); //将0xF4写入发送寄存器中待发送
SPI_Malloc_DATA(); //分配内存
//测试!!!!!!!
//test_init();
}
//******************************************************************************
//name: SPI_Response_Byte
//introduce: SPI从机应答函数
//parameter: none
//return: none
//******************************************************************************
static void SPI_Response_Byte(SPI_RESPONSE_BYTE tx)
{
UxDBUF = tx; //写到寄存器里
}
//******************************************************************************
//name: SPI_Malloc_DATA
//introduce: 给通信协议中的核心数据开辟一个缓冲区
//parameter: none
//return: none
//******************************************************************************
static SPI_MALLOC_DATA_STATUS SPI_Malloc_DATA(void)
{
//分配内存
p_spi_protocol_data = osal_mem_alloc(sizeof(SPI_PROTOCOL_DATA)); //申请缓冲区buffer
//判断是否分配成功
if(p_spi_protocol_data){
//内存分配成功,缓冲区置0
osal_memset(p_spi_protocol_data, 0, sizeof(SPI_PROTOCOL_DATA));
return SPI_MALLOC_DATA_RIGHT;
}else{
//内存分配失败,返回错误信息
return SPI_MALLOC_DATA_ERROR;
}
}
//******************************************************************************
//name: SPI_Poll
//introduce: 扫描SPI
//parameter: none
//return: none
//******************************************************************************
void SPI_Poll(void)
{
switch(spi_rx_status)
{
case SPI_RxStatus_Received:
spi_rx_status = SPI_Rx_Resolution();
break;
default:
//spi_rx_status = SPI_RxStatus_Receiving;
break;
}
}
//******************************************************************************
//name: SPI_Rx_Resolution
//introduce: 解析接收到的SPI数据
//parameter: none
//return: none
//******************************************************************************
static SPI_RXSTATUS SPI_Rx_Resolution(void)
{
uint8 length = spi_rx[0];
uint8 xox_h = spi_rx[length + 1];
uint8 xox_l = spi_rx[length + 2];
uint16 xox = 0;
uint8 eof = spi_rx[length + 3];
//清除缓冲区
osal_memset(p_spi_protocol_data, 0, sizeof(SPI_PROTOCOL_DATA));
//拷贝接收缓冲区
osal_memcpy(p_spi_protocol_data, spi_rx, (length + 3));
//计算校验和
for(uint8 i = 0; i < (length + 1); i++){
//length
if(i == 0){
xox = p_spi_protocol_data->Length;
}
//head
else if(i == 1){
xox ^= p_spi_protocol_data->Head;
}
//sequence
else if(i == 2){
xox ^= p_spi_protocol_data->Sequence;
}
//binary
else{
xox ^= p_spi_protocol_data->Binary[i - 3];
}
}
//比较校验和
if((((uint8)(xox >> 8) & 0xff) != xox_h) || ((uint8)(xox & 0xff) != xox_l)){ //校验和出错
return SPI_RxStatus_Error;
}
//比较EOF
if(eof == SPI_EOF){
//处理数据
if(Head(7) == Head_CTRL){ //CTRL
switch((p_spi_protocol_data->Head) & 0x7F) //内部指令
{
case 0x00:break;
case 0x01:break;
case 0x02:break;
case 0x03:break;
case 0x04:break;
default:break;
}
}
else{ //COMMAND
switch((p_spi_protocol_data->Head) & (1 << 5))
{
case COMMAND_BLE:
break;
case COMMAND_RF:
break;
default:
break;
}
}
return SPI_RxStatus_Right;
}
else{
return SPI_RxStatus_Error;
}
}
//******************************************************************************
//name: SPI_Packet_Receive
//introduce: SPI数据包接收
//parameter: none
//return: 0:接收正常,1数据全部接收完毕,2数据出错,3扫描超时
//******************************************************************************
static uint8 SPI_Packet_Receive(void)
{
uint8 ch = UxDBUF; //接收数据
switch (spiRxSte)
{
//包头
case spiRxSteSOF: //包头
DATA_RESET();
if (ch == SPI_SOF){
spiRxSte = spiRxSteLen; //包头正常,指向长度段
check_time = 0;
}
else if (ch == 0xF5){ //超时处理
if(check_time++ > 200){
check_time = 0;
return 3;
}
}
else{
return 2; //包头接收出错
}
break;
//数据长度
case spiRxSteLen: //数据长度
if((ch >= 3) && (ch <= 34)){
spi_rx[spiRxIndex++] = ch; //保存数据长度
spiRxSte = spiRxSteData; //指向数据接收
}
else{
DATA_RESET();
return 2; //包头接收出错
}
break;
//其他数据
case spiRxSteData:
spi_rx[spiRxIndex] = ch; //保存数据
if(spiRxIndex++ == (spi_rx[0] + 3)){ //判断数据是否接收完
DATA_RESET();
return 1; //接收完毕
}
break;
default:
DATA_RESET();
return 2; //数据出错
break;
}
return 0; //正常
}
//******************************************************************************
//name: SPI_Status_Judge
//introduce: 状态判断
//parameter: status:当前状态
//return: 0:接收正常,1数据全部接收完毕,2数据出错
//******************************************************************************
static SPI_RXSTATUS SPI_Status_Judge(uint8 status)
{
switch(status)
{
//正在接收
case 0:
return SPI_RxStatus_Receiving;
//接收完毕
case 1:
return SPI_RxStatus_Received;
//接收出错
case 2:
return SPI_RxStatus_Error;
//扫描超时出错
case 3:
return SPI_RxStatus_Error;
default:
return SPI_RxStatus_Error;
}
}
//******************************************************************************
//name: SPI_Status_Deal
//introduce: 状态处理
//parameter: none
//return: none
//******************************************************************************
static void SPI_Status_Deal(SPI_RXSTATUS status)
{
switch(status)
{
//正在接收
case SPI_RxStatus_Receiving:
SPI_Response_Byte(RESPONSE_RECEIVING);
break;
//接收完毕
case SPI_RxStatus_Received:
SPI_Response_Byte(RESPONSE_RECEIVING);
break;
//接收出错
case SPI_RxStatus_Error:
spi_rx_status = SPI_RxStatus_Receiving; //下次状态改回接收
SPI_Response_Byte(RESPONSE_RESEND);
break;
default:break;
}
}
//******************************************************************************
//name: SPI_Rx_ISR
//introduce: SPI接收中断函数
//parameter: none
//return: none
//******************************************************************************
#pragma vector = URX1_VECTOR
__interrupt void SPI_Rx_ISR(void)
{
uint8 status = 0;
HAL_ENTER_ISR();
if(UxCSR & CSR_RX_BYTE){ //receive a byte
//test();
switch(spi_rx_status)
{
case SPI_RxStatus_Receiving:
status = SPI_Packet_Receive(); //接收数据
spi_rx_status = SPI_Status_Judge(status); //判断状态
SPI_Status_Deal(spi_rx_status); //处理数据
break;
case SPI_RxStatus_Received:
SPI_Response_Byte(RESPONSE_RECEIVING); //在接收完毕的状态,一直回0xF4。等待轮询改变状态
break;
case SPI_RxStatus_Right:
spi_rx_status = SPI_RxStatus_Receiving; //下次状态改回接收
SPI_Response_Byte(RESPONSE_RECEIVED);
break;
case SPI_RxStatus_Error:
spi_rx_status = SPI_RxStatus_Receiving; //下次状态改回接收
SPI_Response_Byte(RESPONSE_RESEND);
break;
default:
break;
}
}
HAL_EXIT_ISR();
}
#ifndef _SPI_H_
#define _SPI_H_
void SPI_Init(void);
void SPI_Poll(void);
#endif
void Hal_ProcessPoll ()
{
SPI_Poll();
/* UART Poll */
#if (defined HAL_UART) && (HAL_UART == TRUE)
HalUARTPoll();
#endif
/* HID poll */
#if (defined HAL_HID) && (HAL_HID == TRUE)
usbHidProcessEvents();
#endif
#if defined( POWER_SAVING )
/* Allow sleep before the next OSAL event loop */
ALLOW_SLEEP_MODE();
#endif
}
在主轮询中加入SPI的poll轮询函数。
void SimpleBLEPeripheral_Init( uint8 task_id )
{
simpleBLEPeripheral_TaskID = task_id;
HCI_EXT_HaltDuringRfCmd(HCI_EXT_HALT_DURING_RF_DISABLE);//在RF期间不关闭mcu
SPI_Init();//spi初始化
……
//HCI_EXT_ClkDivOnHaltCmd( HCI_EXT_ENABLE_CLK_DIVIDE_ON_HALT );//注释掉
……
}