📄 spi_master.c
字号:
//********************************************************************
// File name: spi_master.c
//
// Copyright 2003 Texas Instruments Inc as an unpublished work.
// Created By: Saripalli Ramesh
//
// Version 1.1 (update by RG on 03/01/2004)
//
// Compiler Version (Raisonance V6.10.14)
//
// Module Description:
// SPI Master & Slave Program
//
//
//********************************************************************
#include "legal.c" //Texas Instruments, Inc. copyright and liability
#include <stdio.h>
#include <stdlib.h>
#include "reg1200.h"
#define SET 1
#define CLEAR 0
#define USEC_val (8-1)
#define debug 1
#define RX_BEG ((unsigned char data*) 0x60) // Start address of the RX buffer
#define RX_END ((unsigned char data*) 0x70) // (End-1) address of the RX buffer
#define TX_BEG ((unsigned char data*) 0x70) // Start address of the TX buffer
#define TX_END ((unsigned char data*) 0x80) // (End-1) address of the TX buffer
#define autobaud() ((void (code *) (void)) 0xFBFA) () // MSC1200
extern char spim_send_recv_byte(char);
extern unsigned long unipolar(void);
void stop_spi(void);
void init_spi_slave(void);
void init_spi_master(void);
sbit SCLK=P3^6;
sbit SDA=P1^2;
sbit SSN=P1^1;
sbit ADC_CS = P1^0;
char data *rxhead, *rxtail, *txhead, *txtail;
bit rxbuf_full, txbuf_full, rxbuf_empty, txbuf_empty;
void reset_pointers(void) {
rxhead = RX_BEG;
rxtail=RX_BEG;
txhead=TX_BEG;
txtail=TX_BEG;
rxbuf_full=0;
txbuf_full=0;
rxbuf_empty=1;
txbuf_empty=1;
}
//void interrupt_isr(void) interrupt 6 {
//char k;
//}
void int2_isr(void) interrupt 8 {
stop_spi();
}
void int3_isr(void) interrupt 9 {
init_spi_slave();
EX2=SET; // Interrupt2 is enabled which is active high, edge sensitive
}
// This routine is to write data to the Rx buffer at the head location.
// The routine writes the data if there is space available in the buffer, if not the data is trashed.
void rxbuf_write(char in_data) {
if(rxbuf_full==1) { // RX Buffer full so the received data is trashed
if(debug) printf("Data overflow than the buffer\n");
}
else { // Space available in the RX buffer.
*rxhead=in_data; // Write the input data to the rxhead pointer
rxhead++; // Increment the rx head pointer
rxbuf_empty=0; // Irrepectively of the rxbuf_empty value set it to zero
if(rxhead==RX_END) { rxhead=RX_BEG;} // If the rxhead is equal to the end then set it back to the begining
if(rxhead==rxtail) { rxbuf_full=1;} // If the head and tail are equal then it means that the buffer is full
}
}
// This subroutine is to read data from the RX buffer from the tail location.
// If the buffer is empty then the routine waits till a new byte is received.
char rxbuf_read(void) {
char tmp_data;
while(rxbuf_empty==1) { } // RX buffer is empty so we wait till we receive a byte
EAI=0; // Disable the interrupt so that the read is not interrupted.
tmp_data=*rxtail; // Store the data in the tmp_data before passing it
rxtail++; // Increment the RX tail pointer
rxbuf_full=0; // Since one byte is consumed the rx buffer is not full, irrespective of what its previous value
if(rxtail==RX_END) { rxtail=RX_BEG; } // If tail reaches end it is moved to the begning
if(rxtail==rxhead) { rxbuf_empty=1; } // If tail and head are the same then the rx buf is empty.
EAI=1; // Enable the interrupts
return(tmp_data);
}
// This routine is to write data to the Tx buffer at the head location.
// The routine waits till the tx buffer is not full.
void txbuf_write(char in_data) {
while(txbuf_full==1) { } // Wait untill the Tx Buffer is not full.
EAI=0; // Disable the interrupt so that the write is not interrupted.
*txhead=in_data; // Write the input data to the txhead pointer
txhead++; // Increment the tx head pointer
txbuf_empty=0; // Irrepectively of the txbuf_empty value set it to zero
if(txhead==TX_END) { txhead=TX_BEG;} // If the txhead is equal to the end then set it back to the begining
if(txhead==txtail) { txbuf_full=1;} // If the head and tail are equal then it means that the buffer is full
EAI=1; // Enable the interrupts
}
// This subroutine is to read data from the TX buffer from the tail location.
// If the buffer is empty then it passes FFh.
char txbuf_read(void) {
char tmp_data=0xFF;
if(txbuf_empty==1) { // Tx buffer is empty so we cannot send a valid data
if(debug) printf("Data underflow on Tx buffer\n");
}
else { // When there is data in the TX buffer
tmp_data=*txtail; // Store the data in the tmp_data before passing it
txtail++; // Increment the Tx tail pointer
txbuf_full=0; // Since one byte is consumed the tx buffer is not full, irrespective of what its previous value
if(txtail==TX_END) { txtail=TX_BEG; } // If tail reaches end it is moved to the begning
if(txtail==txhead) { txbuf_empty=1; } // If tail and head are the same then the tx buf is empty.
}
return(tmp_data);
}
void init_spi_slave(void) {
P1DDRL=0xD0; // P12(SOUT)=output and P13(SIN)=Input.
P3DDRH=0x30; // P36(SCLK)=Output
PDCON&=0xFE; // Enable SPI/I2C module
SPICON=0x00; // SPI mode, CPOL=0, SCK idle low.
reset_pointers();
SPIDATA=0x00;
AIE=0x04;
AI=CLEAR;
EAI=SET;
}
void stop_spi(void) {
P1DDRL=0x00; // P12(SOUT)=output and P13(SIN)=Input.
P3DDRH=0x00; // P36(SCLK)=Output
PDCON|=0x01; // Disable SPI/I2C module
P1=0xFF;
P3=0xFF;
}
void init_spi_master(void) {
SSN=SET; // Disable the slave
P1DDRL=0xD4; // P11(SSN)=output,P12(SOUT)=output and P13(SIN)=Input.
P3DDRH=0x10; // P36(SCLK)=Output
PDCON&=0xFE; // Enable SPI/I2C module
SPICON=0x00; // SPI mode, CPOL=0, SCK idle low.
SCLK=CLEAR;
reset_pointers();
}
// This routine takes in a byte and sends it on SPI bus. The received data is read and is written to the RX buffer.
void spim_send_recv_data ( char tx_data ) {
char k;
k=tx_data;
rxbuf_write(spim_send_recv_byte(k));
}
#define LedOn 0
#define LedOff 1
sbit RedLed = P3^4;
sbit YelLed = P3^5;
void adc_spi_dacout (void)
{
unsigned short int data_value;
unsigned int adc16, value0, value1, value2;
char i;
data_value=unipolar();
ADC_CS = CLEAR;
SSN = SET; // Sync pluse for the DAC's SPI
SSN = CLEAR;
// Note: To avoid SPI overflow, sufficient delay between
// every 3 SPIDATA write is needed.
value0 = spim_send_recv_byte(0x00); // Normal DAC Mode
value1 = spim_send_recv_byte((char)(data_value>>8 & 0x000ff)); // Send the Hi-Byte of the ADC result
value2 = spim_send_recv_byte((char)(data_value & 0x000ff)); // Send the middle-Byte of the ADC result
ADC_CS = SET;
reset_pointers();
adc16 = value0 << 14 | value1 << 6 | value2 >> 2;
printf("V=%6.4f\ti=%d\r",adc16*2.5/65536, i);
IDAC = i++;
if (i==0){
YelLed = RedLed;
RedLed = !RedLed;
}
}
void main(void) {
int i, sel;
char c;
// AutoBaud routine
CKCON = 0x10; // 0 MOVX cycle stretch and clk/4
TCON=0x00;
autobaud();
// End of Autobaud
printf("\x1b[2J");
printf("\t\t\t\tMSC1200 SPI Master/Slave \n");
printf("1)Master 2)Slave\n");
scanf("%d", &sel);
if(sel==1) {
printf("SPI Master \n");
init_spi_master();
PDCON &= 0xB7; // Turn on IDAC, ADC-Vref
// ADC settings
ACLK = 1; // ACLK = 8MHz/(1+1)= 4MHz
DECIMATION = 150; // Data Rate = ACLK/64/Decimation ~ 416Hz
ADMUX = 0x08; // +ve connected to AIN0, -ve connected to AINCOM
ADCON0 = 0x30; // BOD off, Internal Vref @ 2.5V, Buff off, PGA 1
ADCON1 = 0x41; // Unipolar, Auto filter setting, self calibration for offset and gain
while(1) { adc_spi_dacout(); }
}
else {
printf("SPI Slave \n");
EX3=SET; // Interrupt3 is enabled which is active low, edge sensitive
EA=SET; // The external interrupts are enabled.
}
while(1) { }
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -