📄 ssp.c
字号:
/***********************************************Copyright (c)*********************************************
** Guangzou ZLG-MCU Development Co.,LTD.
**
** http://www.zlgmcu.com
**
**--------------File Info---------------------------------------------------------------------------------
** File name: SSP.h
** Last modified Date: 2007-11-22
** Last Version: 2.0
** Descriptions: SSP 功能部件头文件,供用户使用.
**
**--------------------------------------------------------------------------------------------------------
** Created by: WangGuoguang
** Created date: 2007-11-14
** Version: 1.0
** Descriptions: 此头文件可在config.h中包含.
**
**--------------------------------------------------------------------------------------------------------
** Modified by: WangGuoguang
** Modified Date: 2007-11-22
** Version: 2.0
** Descriptions: 调试通过,并实现预定功能.
**
*********************************************************************************************************/
#include "config.h" /* 系统头文件 */
#include "SSPPrivate.h" /* 软件包内部私有头文件 */
#include "SSP.h" /* 软件包内部模块头文件 */
/********************************************************************************************************
裁剪是否使用此软件包,当 SSP_FUN_LIB = 0,从而不编译.
*********************************************************************************************************/
#if SSP_FUN_LIB > 0
/*********************************************************************************************************
定义操作 SSP 器件的结构体.
**********************************************************************************************************/
static __SSP_INFO __SSP_SPI_Data;
static __SSP_PARAM __SSP_SPI_Param;
/*********************************************************************************************************
下面使用指针数组(结构体指针数组)来保存指向各个(SPI ,SSI ...)信息结构体的指针,方便对该驱动的扩展
**********************************************************************************************************/
const __PSSP_INFO __GpSSPInfoData[__SSP_MAX_NUM] = {&__SSP_SPI_Data};
const __PSSP_PARAM __GpSSPSpiParam[__SSP_MAX_NUM] = {&__SSP_SPI_Param};
/*********************************************************************************************************
下面定义了 SSP 基地址值,如果有多个SSP总线接口(SPI ,SSI ...),器件可以在该位置添加相应的基地址即可
**********************************************************************************************************/
const uint32 __GuiSSPBaseAddrTab[__SSP_MAX_NUM] = {SSP0_BASE_ADDR};
/*********************************************************************************************************
定义 数据缓冲区数组,以保存 SSP 器件的通信数据.
**********************************************************************************************************/
static uint8 __SSP_SendQueue[__SSP_MAX_NUM][SSP_DATA_QUEUE_NUM];
static uint8 __SSP_RecvQueue[__SSP_MAX_NUM][SSP_DATA_QUEUE_NUM];
/*********************************************************************************************************
** Function name: __sspInit()
**
** Descriptions: SSP初始化函数,内部使用
** Input parameters: uiID 设备号,例如0表示使用SSP0
** puiParam 传入参数的结构体
** pRsv 保留参数,为软件包升级扩展所用.
**
** Returned value: 初始化失败: OPERATE_FAIL
** 管脚连接错误: PIN_ERR
** 初始化成功: OPERATE_SUCCESS
*********************************************************************************************************/
static uint32 __sspInit (uint32 uiID,
uint32 *puiParam,
void *pRsv)
{
volatile uint32 uiOffsetBase;
volatile uint32 *puiBaseAddr;
uint8 ucCPSDVSR;
uint8 ucSCR;
if ((uiID >= __SSP_MAX_NUM) || (puiParam == NULL)) { /* 检查参数有效性 */
return (uint32)(OPERATE_FAIL);
}
pRsv = pRsv ;
/*
* 管脚参数判断
*/
if (puiParam[SSPType] == SPI) {
if (((PINSEL0 >> 28) & 0x03) != P0_14_SCK1 || /* SCK1 */
((PINSEL1 >> 6 ) & 0x03) != P0_19_MISO1 || /* MISO1 */
((PINSEL1 >> 8 ) & 0x03) != P0_20_MOSI1 || /* MOSI1 */
((PINSEL1 >> 10) & 0x03) != P0_21_SSEL1 ) { /* SSEL1 */
return (PIN_ERR);
}
}
/*
* 处理波特率参数
*/
if (puiParam[SSPBaudRate] < 20000) { /* 最佳波特率范围不能小于20K. */
puiParam[SSPBaudRate] = 30000;
}
if ((Fpclk / puiParam[SSPBaudRate]) > 254) {
if ((Fpclk / puiParam[SSPBaudRate]) > (254 * 256)) { /* ucCPSDVSR 最大值为254 */
return (uint32)(OPERATE_FAIL); /* ucSCR 最大值为255 */
}
ucCPSDVSR = 254;
ucSCR = (uint8)((Fpclk / puiParam[SSPBaudRate]) / ucCPSDVSR - 1);
} else {
ucCPSDVSR = (uint8)((Fpclk / puiParam[SSPBaudRate]) & 0xFE);
ucSCR = 0;
}
/*
* 初始化器件结构体地址信息
*/
IRQDisable(); /* 关IRQ中断 */
__GpSSPInfoData[uiID]->uiOffsetBase = __SSP_OFFSET_BASE;
__GpSSPInfoData[uiID]->puiAddrBase = (uint32*)__GuiSSPBaseAddrTab[uiID];
__GpSSPInfoData[uiID]->SspSendQueAddr = (__PDATA_QUEUE)__SSP_SendQueue[uiID];
__GpSSPInfoData[uiID]->SspRecvQueAddr = (__PDATA_QUEUE)__SSP_RecvQueue[uiID];
IRQEnable(); /* 开IRQ中断 */
/*
* 初始化部件功能寄存器,不影响保留位的值
*/
uiOffsetBase = __GpSSPInfoData[uiID]->uiOffsetBase;
puiBaseAddr = __GpSSPInfoData[uiID]->puiAddrBase;
puiBaseAddr[__B_SSP_SSPCR0 << uiOffsetBase] = (ucSCR << 8) |
(puiParam[CPHA] << 7) |
(puiParam[CHOL] << 6) |
(puiParam[SSPType] << 4) |
((puiParam[BitsLen] - 1)<< 0);
puiBaseAddr[__B_SSP_SSPCR1 << uiOffsetBase] |= (0x00 << 3) |
(puiParam[MasterSlaver] << 2) |
(0x00 << 1) |
(0x00 << 0);
/* 首先禁止SSP使能,在后面打开 */
puiBaseAddr[__B_SSP_SSPCPSR << uiOffsetBase] = ucCPSDVSR; /* SSP时钟分频寄存器 */
/*
* 使能接收中断:至少一半为满中断,超时中断,不打开溢出中断(0x07 -> 0x06);
* 此时不能使能发送中断,否则会有中断始终有效.(注:发送中断在写数据时使能)
*/
puiBaseAddr[__B_SSP_SSPIMSC << uiOffsetBase] |= 0x06; /* SSPIMSC : 中断屏蔽/使能 */
puiBaseAddr[__B_SSP_SSPICR << uiOffsetBase] |= 0x03; /* 清除中断标志 */
puiBaseAddr[__B_SSP_SSPCR1 << uiOffsetBase] |= 0x01 << 1; /* 使能SSP (必须在最后配置使能)*/
/*
* 记录一些信息在设备结构体中
*/
IRQDisable(); /* 关IRQ中断 */
__GpSSPInfoData[uiID]->uiSSPID = uiID; /* 记录在设备结构体中 */
__GpSSPInfoData[uiID]->uiSSPMode = puiParam[SSPType];
__GpSSPInfoData[uiID]->usSspFrameNum = 0x08; /* SSP帧个数为8,此值不可更改! */
__GpSSPInfoData[uiID]->ucSendIntEn = __SSP_W_INT_DISABLE; /* 标志写中断没打开 */
__GpSSPInfoData[uiID]->ucDataLen = (uint8)puiParam[BitsLen];
__GpSSPInfoData[uiID]->ucMasterSlave = (uint8)puiParam[MasterSlaver];
__GpSSPInfoData[uiID]->ucSSPState = __SSP_IDLE;
__GpSSPSpiParam[uiID]->SSPType = SPI; /* 记录在参数结构体中 */
__GpSSPSpiParam[uiID]->MasterSlaver = (uint8)puiParam[MasterSlaver];
__GpSSPSpiParam[uiID]->CPHA = (uint8)puiParam[CPHA];
__GpSSPSpiParam[uiID]->CHOL = (uint8)puiParam[CHOL];
__GpSSPSpiParam[uiID]->SSPBaudRate = puiParam[SSPBaudRate];
__GpSSPSpiParam[uiID]->BitsLen = (uint8)puiParam[BitsLen];
__GpSSPInfoData[uiID]->pSspParam = __GpSSPSpiParam[uiID];
IRQEnable(); /* 开IRQ中断 */
return (uint32)(OPERATE_SUCCESS);
}
/*********************************************************************************************************
** Function name: sspInit()
**
** Descriptions: SSP初始化函数,使用字符串传入参数
** Input parameters: uiID 设备号,例如0表示使用SSP0
** puiParam 传入参数的字符串指针,参数列表和取值意义如下
** SSPType : 总线类型:SPI,SSI,Microwire
** MasterSlaver : 0: 主机 1.从机
** SSPBaudRate : 如设为SPI总线类型,波特率 <= Fpclk / 2
** BitsLen : 帧长度 = 4, 8, 16位
** CPHA : 时钟相位 = 0, 1
** CHOL : 时钟极性 = 0, 1.
** pRsv 保留参数,为软件包升级扩展所用.
**
** Returned value: 初始化失败: OPERATE_FAIL
** 初始化成功: OPERATE_SUCCESS
*********************************************************************************************************/
uint32 sspInit (uint32 uiID,
char *pcArg,
char *pRsv)
{
volatile uint32 *puiSspPCtrl; /* SSP功率控制寄存器基址指针 */
static uint32 uiParam[6]={0,0,550000,8,0,0};
if ((uiID >= __SSP_MAX_NUM) | (pcArg == NULL)) { /* 检查参数有效性 */
return (uint32)(OPERATE_FAIL);
}
pRsv = pRsv ; /* 为了防止编译器警告 */
ImpCmd(Tab_SSP, pcArg, uiParam); /* 解析字符串参数 */
/*
* 过滤输入字符参数
*/
if (uiParam[SSPType] > MICROWIRE) { /* 总线类型:SPI,SSI,Microwire */
uiParam[SSPType] = SPI;
}
if (uiParam[MasterSlaver] > 1) {
uiParam[MasterSlaver] = 0; /* 默认为主机模式 从机:1 主机:0*/
}
if (uiParam[SSPType] == SPI) { /* 若为SPI类型,速率<= (Fpclk/8)*/
if (uiParam[SSPBaudRate] > (Fpclk / 2)) {
uiParam[SSPBaudRate] = Fpclk / 2;
}
}
if ((uiParam[BitsLen] != 4 ) &&
(uiParam[BitsLen] != 8 ) &&
(uiParam[BitsLen] != 16)) {
uiParam[BitsLen] = 8; /* 默认为每帧8位 */
}
if (uiParam[CPHA] > 1) { /* 输出时钟相位 */
uiParam[CPHA] = 0;
}
if (uiParam[CHOL] > 1) { /* 输出时钟极性 */
uiParam[CHOL] = 0;
}
/*
* 打开PCONP功率管理中的SSP外设,必须这样处理.
*/
puiSspPCtrl = (uint32*)SCB_BASE_ADDR;
puiSspPCtrl[__B_SSP_PCONP] &= (~(0x01 << 10)); /* 关闭SPI1功能外设(默认是打开)*/
puiSspPCtrl[__B_SSP_PCONP] |= (0x01 << 21); /* 打开SSP功能外设 */
/*
* 创建数据缓存队列
*/
if (QueueCreate(__SSP_SendQueue[uiID],sizeof(__SSP_SendQueue[uiID]),NULL,NULL) == QUEUE_OK) {
if (QueueCreate(__SSP_RecvQueue[uiID],sizeof(__SSP_RecvQueue[uiID]),NULL,NULL) == QUEUE_OK) {
__GpSSPInfoData[uiID]->uiSQueueState = __SSP_QUEUE_EMPTY;/* 发队列为空状态 */
__GpSSPInfoData[uiID]->uiRQueueState = __SSP_QUEUE_EMPTY;/* 收队列为空状态 */
__GpSSPInfoData[uiID]->uiHardSFIFOState = __SSP_FIFO_EMPTY; /* 发硬FIFO为空状态 */
__GpSSPInfoData[uiID]->uiHardRFIFOState = __SSP_FIFO_EMPTY; /* 收硬FIFO为空状态 */
return (__sspInit(uiID,uiParam,pRsv));
}
}
return (uint32)(OPERATE_FAIL);
}
/*********************************************************************************************************
** Function name: sspSetMode
**
** Descriptions: SSP初始化函数,使用字符串传入参数
** Input parameters: uiID 设备号,例如0表示使用SSP0
** puiParam 传入参数的字符串指针,参数列表和取值意义如下
** SSPType : 总线类型:SPI,SSI,Microwire
** MasterSlaver : 0: 主机 1.从机
** SSPBaudRate : 如设为SPI总线类型,波特率 <= Fpclk / 8
** BitsLen : 帧长度 = 4, 8, 16位
** CPHA : 时钟相位 = 0, 1
** CHOL : 时钟极性 = 0, 1.
** pRsv 保留参数,为软件包升级扩展所用.
**
** Returned value: 操作失败: OPERATE_FAIL
** 操作成功: OPERATE_SUCCESS
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -