📄 comm_spi.c
字号:
//====================================================================
//--- COPYRIGHT
//====================================================================
// Copyright 2006 Microchip Technology Inc.
//
// Microchip Technology Inc. ("Microchip") licenses this software to
// you solely for use with Microchip products. The software is owned
// by Microchip and is protected under applicable copyright laws. All
// rights reserved.
//
// SOFTWARE IS PROVIDED IN AN "AS IS." MICROCHIP EXPRESSLY DISCLAIMS ANY
// WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE, OR NON-INFRINGEMENT. IN NO EVENT SHALL MICROCHIP
// BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL
// DAMAGES, LOST PROFITS OR LOST DATA, HARM TO YOUR EQUIPMENT, COST OF
// PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
// BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF),
// ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER SIMILAR COSTS.
//
//====================================================================
//--- TITLE
//====================================================================
// Filename: comm_spi.c
// Microcontroller: PIC18F2550
// Compiled using: C18 V3.00
//
// Author: Mark Enochson
// Company: Microchip Technology Inc.
//
//====================================================================
//--- DESCRIPTION
//====================================================================
//
//--- COMM_SPI
//
// communications controller: SPI
// uses MSSP hardware assist
//
//--- comm_spi_init()
// initialize module per CONTROL_BLOCK data
//
//--- comm_spi_svc()
// SPI script service
//
//--- comm_spi_reset()
// "reset" comm control (f/w, h/w) to benign state
//
//--- comm_spi_postproc()
// spi script service post processing
//
//--- comm_spi_svc()
// SPI script service
//
//====================================================================
//--- HISTORY
//====================================================================
//
// 0001 - 08-01-06 - ME
// - initial release
//
//====================================================================
//==========================================================
//--- INCLUDES
//==========================================================
#include "project.h"
#include "comm_gen.h"
#include "comm_spi.h"
#include "cbuf.h"
//==========================================================
//--- DEFINITIONS / DECLARATIONS
//==========================================================
// none
//==========================================================
//--- comm_spi_init()
// initialize module per CONTROL_BLOCK data
//==========================================================
TD_BYTE comm_spi_init(void)
{
//---------------------------------------------
comm_spi_reset();
//---------------------------------------------
//--- if MASTER or SLAVE
//---------------------------------------------
if((COMM_CB_MODE_REG == COMM_MODE_SPI_M) ||
(COMM_CB_MODE_REG == COMM_MODE_SPI_S) ||
(COMM_CB_MODE_REG == COMM_MODE_MWIRE_M))
{
SSPSTATbits.SMP = 0;
if(COMM_CB_SPI_CONFIG_SMP_FLAG)
SSPSTATbits.SMP = 0;
SSPSTATbits.CKE = 0;
if(COMM_CB_SPI_CONFIG_CKE_FLAG)
SSPSTATbits.CKE = 1;
//--- MASTER-specific
if((COMM_CB_MODE_REG == COMM_MODE_SPI_M) ||
(COMM_CB_MODE_REG == COMM_MODE_MWIRE_M))
{
SSPCON1 = SSPCON1_SPI_MODE_MASTER;
COMM_SPI_SCK_TRIS = 0;
if(COMM_CB_SPI_CONFIG_CSPOL_FLAG)
COMM_SPI_CS_PIN = 1;
else
COMM_SPI_CS_PIN = 0;
COMM_SPI_CS_TRIS = 0;
}
//--- SLAVE-specific
else
{
SSPCON1 = SSPCON1_SPI_MODE_SLAVE_NOSS;
COMM_SPI_SCK_TRIS = 1;
}
if(COMM_CB_SPI_CONFIG_CKP_FLAG)
SSPCON1bits.CKP = 1;
COMM_SB_SPI_CONFIG_REG = COMM_CB_SPI_CONFIG_REG;
//---
COMM_SPI_SDO_TRIS = 0;
COMM_SPI_SDI_TRIS = 1;
//--- setup TMR2 for bit rate
COMM_SB_SPI_BITRATE_PRESCALE_REG = COMM_CB_SPI_BITRATE_PRESCALE_REG & 0x03;
COMM_SB_SPI_BITRATE_SCALE_REG = COMM_CB_SPI_BITRATE_SCALE_REG;
T2CON = COMM_SB_SPI_BITRATE_PRESCALE_REG;
PR2 = COMM_SB_SPI_BITRATE_SCALE_REG;
T2CONbits.TMR2ON = 1;
//---
SSPCON1bits.SSPEN = 1;
}
else
{
//comm_spi_reset();
return(1);
}
return(0);
}
//==========================================================
//--- comm_spi_reset()
// "reset" comm control (f/w, h/w) to benign state
//==========================================================
void comm_spi_reset(void)
{
COMM_SB_SPI_REG12 = 0;
COMM_SB_SPI_REG13 = 0;
COMM_SB_SPI_REG14 = 0;
COMM_SB_SPI_REG15 = 0;
COMM_SB_SPI_REG16 = 0;
COMM_SB_SPI_REG17 = 0;
COMM_SB_SPI_REG18 = 0;
COMM_SB_SPI_REG19 = 0;
COMM_SB_SPI_ERR_REG = 0;
COMM_SB_SPI_CONFIG_REG = 0;
COMM_SB_SPI_BITRATE_PRESCALE_REG = 0;
COMM_SB_SPI_BITRATE_SCALE_REG = 0;
SSPCON1 = SSPCON1_SPI_MODE_IDLE;
T2CONbits.TMR2ON = 0;
COMM_SPI_SDO_TRIS = 1;
COMM_SPI_SDI_TRIS = 1;
COMM_SPI_SCK_TRIS = 1;
COMM_SPI_CS_TRIS = 1;
COMM_SPI_SDI_2_TRIS = 1;
COMM_SPI_SDO_2_TRIS = 1;
COMM_SPI_SCK_2_TRIS = 1;
COMM_SPI_CS_2_TRIS = 1;
}
//==========================================================
//--- comm_spi_postproc()
// spi script service post processing
//
// called by comm_gen after script service is "released"
// i.e. forced looping off
// "forced looping" keeps execution in the service loop
// to reduce delay/overhead between critical script entities
//==========================================================
void comm_spi_postproc(void)
{
//-----------------------------------
//--- transaction error
//-----------------------------------
COMM_7_FLAG = 0;
if(SSPCON1bits.WCOL)
{
COMM_7_FLAG = 1;
SSPCON1bits.WCOL = 0;
COMM_SB_SPI_WCOL_FLAG = 1;
}
if(SSPCON1bits.SSPOV)
{
COMM_7_FLAG = 1;
SSPCON1bits.SSPOV = 0;
COMM_SB_SPI_SSPOV_FLAG = 1;
}
if(COMM_7_FLAG)
{
if(COMM_CB_SPI_EVENT_STATUS_ERR_FLAG)
{
comm_post_event_1b(COMM_TAG_SPI_EVENT_STATUS_ERR, COMM_SB_SPI_ERR_REG);
}
}
//-----------------------------------
//--- composite error
//-----------------------------------
if(COMM_SB_SPI_ERR_REG & COMM_SB_SPI_ERR_REG_MASK)
{
COMM_SB_GEN_ERR_FLAG = 1;
COMM_SB_SPI_ERR_FLAG = 1;
}
//-----------------------------------
//--- save pin states to status block
//-----------------------------------
COMM_SB_SPI_SDI_STATE_FLAG = 0;
if(COMM_SPI_SDI_2_PIN)
COMM_SB_SPI_SDI_STATE_FLAG = 1;
COMM_SB_SPI_SDO_STATE_FLAG = 0;
if(COMM_SPI_SDI_2_PIN)
COMM_SB_SPI_SDO_STATE_FLAG = 1;
COMM_SB_SPI_SCK_STATE_FLAG = 0;
if(COMM_SPI_SCK_2_PIN)
COMM_SB_SPI_SCK_STATE_FLAG = 1;
COMM_SB_SPI_CS_STATE_FLAG = 0;
if(COMM_SPI_CS_2_PIN)
COMM_SB_SPI_CS_STATE_FLAG = 1;
}
//==========================================================
//--- comm_spi_svc()
// SPI script service
//
// script commands/data are taken from the buffer queue
// flag "COMM_PROC_LOOP_FLAG" is used to keep program
// execution in script processing between critical
// entries in the script
//==========================================================
void comm_spi_svc(void)
{
//---------------------------------------------
//--- SWITCH CONTROLLER STATE
//---------------------------------------------
switch(comm_state)
{
//====================================================
/*
case COMM_TAG_SPI_RESET:
comm_spi_reset();
comm_state = COMM_STATE_GEN_NEXT;
break;
*/
//====================================================
case COMM_TAG_SPI_INIT:
comm_spi_init();
comm_state = COMM_STATE_GEN_NEXT;
break;
//====================================================
case COMM_TAG_SPI_DATAIO_OUT:
COMM_4_FLAG = 0;
COMM_5_FLAG = 1;
comm_state = COMM_STATE_SPI_DATAIO;
COMM_PROC_LOOP_FLAG = 1;
break;
//====================================================
case COMM_TAG_SPI_DATAIO_IN:
COMM_4_FLAG = 1;
COMM_5_FLAG = 0;
comm_state = COMM_STATE_SPI_DATAIO;
COMM_PROC_LOOP_FLAG = 1;
break;
//====================================================
case COMM_TAG_SPI_DATAIO_INOUT:
COMM_4_FLAG = 1;
COMM_5_FLAG = 1;
comm_state = COMM_STATE_SPI_DATAIO;
COMM_PROC_LOOP_FLAG = 1;
break;
//====================================================
case COMM_STATE_SPI_DATAIO:
//====================================================
// state used by DATAIO_IN, DATAIO_OUT & DATAIO_INOUT
// COMM_4_FLAG: rd enabled
// COMM_5_FLAG: wr enabled
//====================================================
//-----------------------------
//--- GET BYTE COUNT (0=>256)
//-----------------------------
if(not COMM_0_FLAG)
{
if(comm_data_get())
{
comm_cmnd_count_2 = comm_data; // load byte count
COMM_0_FLAG = 1;
PIR1bits.SSPIF = 0; // pre-clear interrupt
if(not COMM_CB_SPI_CONFIG_DAOD_FLAG)
{
if(COMM_5_FLAG)
COMM_SPI_SDO_TRIS = 0;
else
COMM_SPI_SDO_TRIS = 1;
}
}
}
//-------------------------------
//--- WRITE
//-------------------------------
else if(not COMM_1_FLAG)
{
PIR1bits.SSPIF = 0;
if(COMM_5_FLAG) // WRITE enabled ?
{
if(not comm_data_get()) // get HOST data byte
break;
SSPBUF = comm_data;
if(COMM_CB_SPI_EVENT_BYTE_TX_FLAG)
comm_post_event_1b(COMM_TAG_SPI_EVENT_BYTE_TX, comm_data);
}
else
SSPBUF = 0; // DUMMY data
COMM_1_FLAG = 1;
comm_led_busy_data();
}
//-------------------------------
//--- WAIT BYTE COMPLETE
//-------------------------------
else
{
//-------------------------------
//--- WAIT FOR INT
//-------------------------------
if(not PIR1bits.SSPIF)
break;
//-------------------------------
//--- READ BYTE
//-------------------------------
comm_data = SSPBUF; // read/save serial data
PIR1bits.SSPIF = 0;
if(COMM_4_FLAG) // if READ enabled, post data
{
if(COMM_CB_SPI_EVENT_BYTE_RX_FLAG)
comm_post_event_1b(COMM_TAG_SPI_EVENT_BYTE_RX, comm_data);
comm_post_data();
comm_led_busy_data();
}
//-----------------------------
//--- CHECK BYTE COUNT
//-----------------------------
comm_cmnd_count_2--;
if(comm_cmnd_count_2)
{
COMM_1_FLAG = 0;
COMM_PROC_LOOP_FLAG = 1;
}
else
{
comm_state = COMM_STATE_GEN_NEXT;
break;
}
}
break;
//====================================================
case COMM_TAG_SPI_BITRATE:
if(not COMM_0_FLAG)
{
if(comm_data_get())
{
COMM_SB_SPI_BITRATE_SCALE_REG = comm_data;
COMM_0_FLAG = 1;
COMM_PROC_LOOP_FLAG = 1;
}
}
else
{
if(comm_data_get())
{
COMM_SB_SPI_BITRATE_PRESCALE_REG = comm_data & 0x03;
T2CON = COMM_SB_SPI_BITRATE_PRESCALE_REG;
PR2 = COMM_SB_SPI_BITRATE_SCALE_REG;
T2CONbits.TMR2ON = 1;
comm_state = COMM_STATE_GEN_NEXT;
}
}
break;
//====================================================
case COMM_TAG_SPI_SDO_IN:
COMM_SPI_SDO_TRIS = 1;
comm_state = COMM_STATE_GEN_NEXT;
COMM_PROC_LOOP_FLAG = 1;
break;
//====================================================
case COMM_TAG_SPI_SDO_OUT:
COMM_SPI_SDO_TRIS = 0;
comm_state = COMM_STATE_GEN_NEXT;
COMM_PROC_LOOP_FLAG = 1;
break;
//====================================================
case COMM_TAG_SPI_CS_ON:
if(COMM_CB_SPI_CONFIG_CSPOL_FLAG)
COMM_SPI_CS_PIN = 1;
else
COMM_SPI_CS_PIN = 0;
COMM_SPI_CS_TRIS = 0;
comm_state = COMM_STATE_GEN_NEXT;
COMM_PROC_LOOP_FLAG = 1;
break;
//====================================================
case COMM_TAG_SPI_CS_OFF:
if(COMM_CB_SPI_CONFIG_CSPOL_FLAG)
COMM_SPI_CS_PIN = 0;
else
COMM_SPI_CS_PIN = 1;
COMM_SPI_CS_TRIS = 0;
comm_state = COMM_STATE_GEN_NEXT;
COMM_PROC_LOOP_FLAG = 1;
break;
//====================================================
default:
COMM_SB_BAD_CMND_FLAG = 1;
break;
} // end SWITCH
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -