Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
/* Copyright (C) 2015 Kristian Sloth Lauszus. All rights reserved.
This software may be distributed and modified under the terms of the GNU
General Public License version 2 (GPL2) as published by the Free Software
Foundation and appearing in the file GPL2.TXT included in the packaging of
this file. Please note that GPL2 Section 2[b] requires that all works based
on this software must also be made publicly available under the terms of
the GPL2 ("Copyleft").
Contact information
-------------------
Kristian Sloth Lauszus
Web : http://www.lauszus.com
e-mail : lauszus@gmail.com
*/
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#if USE_FLOW_SENSOR
#include "SPI.h"
#include "Time.h"
#include "inc/hw_memmap.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/ssi.h"
#include "driverlib/sysctl.h"
static void spiSelect(bool enable) {
GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_3, enable ? 0 : GPIO_PIN_3); // The SS pin is active low
}
void initSPI(void) {
SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0); // Enable SSI0 peripheral
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); // Enable GPIOA peripheral
SysCtlDelay(2); // Insert a few cycles after enabling the peripheral to allow the clock to be fully activated
// Use alternate function
GPIOPinConfigure(GPIO_PA2_SSI0CLK);
GPIOPinConfigure(GPIO_PA4_SSI0RX);
GPIOPinConfigure(GPIO_PA5_SSI0TX);
GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_3); // Set SS as output
spiSelect(false);
GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_2 | GPIO_PIN_4 | GPIO_PIN_5); // Use pins with SSI peripheral
SSIClockSourceSet(SSI0_BASE, SSI_CLOCK_SYSTEM); // Use system clock
// Configure the SSI to MODE3, 2 MHz, and 8-bit data
SSIConfigSetExpClk(SSI0_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_3, SSI_MODE_MASTER, 2e6, 8);
SSIEnable(SSI0_BASE); // Enable the SSI module
uint32_t buf;
while (SSIDataGetNonBlocking(SSI0_BASE, &buf)) {
// Read any residual data from the SSI port. This makes sure the receive
// FIFOs are empty, so we don't read any unwanted junk. This is done here
// because the SPI SSI mode is full-duplex, which allows you to send and
// receive at the same time. The SSIDataGetNonBlocking function returns
// "true" when data was returned, and "false" when no data was returned.
// The "non-blocking" function checks if there is any data in the receive
// FIFO and does not "hang" if there isn't.
}
}
void spiWrite(uint8_t regAddr, uint8_t data) {
spiTransfer(®Addr, 1, &data, NULL, 1);
}
void spiWriteData(uint8_t regAddr, const uint8_t *data, uint32_t length) {
spiTransfer(®Addr, 1, data, NULL, length);
}
uint8_t spiRead(uint8_t regAddr) {
uint8_t data;
spiTransfer(®Addr, 1, NULL, &data, 1);
return data;
}
void spiReadData(uint8_t regAddr, uint8_t *data, uint32_t length) {
spiTransfer(®Addr, 1, NULL, data, length);
}
void spiTransfer(const uint8_t *header, uint16_t headerLength, const uint8_t *sendData, uint8_t *recvData, uint32_t dataLength) {
spiSelect(true);
// First send header
uint32_t buf;
for (uint16_t i = 0; i < headerLength; i++) {
SSIDataPut(SSI0_BASE, header[i]);
SSIDataGet(SSI0_BASE, &buf); // Throw away response
#if USE_FLOW_SENSOR
delayMicroseconds(75); // Wait minimum 75 us in case writing to Motion or Motion_Burst registers
#endif
}
// Send data and read response
for (uint32_t i = 0; i < dataLength; i++) {
if (sendData)
SSIDataPut(SSI0_BASE, sendData[i]); // Send data the pointer is not NULL
else
SSIDataPut(SSI0_BASE, 0); // Send 0
SSIDataGet(SSI0_BASE, &buf); // Receive response
if (recvData)
recvData[i] = buf; // Store response in the buffer
}
spiSelect(false);
}
#endif // USE_FLOW_SENSOR
33ba1246aThis file is pinned to the selected release. Download the original to open it in your design tool.