⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 spi.c

📁 RT-Thread是发展中的下一代微内核嵌入式实时操作系统
💻 C
字号:
/*
 * File      : spi.c
 * This file is part of RT-Thread RTOS
 * COPYRIGHT (C) 2006, RT-Thread Develop Team
 *
 * The license and distribution terms for this file may be
 * found in the file LICENSE in this distribution or at
 * http://openlab.rt-thread.com/license/LICENSE
 *
 * Change Logs:
 * Date           Author       Notes
 * 2006-09-23     Vai      first version (For ARM7TDMI core)
 */

#include "spi.h"

extern void swiDelay(unsigned int duration);

#define REG_SPI_CR      (*(volatile unsigned short*)0x040001C0)
#define REG_SPI_DATA    (*(volatile unsigned short*)0x040001C2)

#define SPI_4MHZ	(0<<0)
#define SPI_2MHZ	(1<<0)
#define SPI_1MHZ	(2<<0)
#define SPI_512KHZ	(3<<0)
#define SPI_BUSY	(1<<7)
#define SPI_POWER	(0<<8)
#define SPI_FIRMWARE	(1<<8)
#define SPI_TOUCH	(2<<8)
#define SPI_8CLOCKS	(0<<10)
#define SPI_16CLOCKS	(1<<10)
#define SPI_SINGLE	(0<<11)
#define SPI_CONTINUOUS	(1<<11)
#define SPI_INTERRUPT	(1<<14)
#define SPI_ENABLE	(1<<15)

#define POWER_READ	(1<<7)
#define POWER_WRITE	(0<<7)
#define POWER_REG(n)	(n)

#define WAIT_FOR_NOT_BUSY() {while (REG_SPI_CR & SPI_BUSY) swiDelay(1);}

static unsigned short touch_read(unsigned int command)
{
	unsigned short result;

	WAIT_FOR_NOT_BUSY();

	// Write the command and wait for it to complete
	REG_SPI_CR = SPI_ENABLE | SPI_CONTINUOUS | SPI_TOUCH | SPI_8CLOCKS | SPI_2MHZ ;
	REG_SPI_DATA = command;
	WAIT_FOR_NOT_BUSY();

	// Write the second command and clock in part of the data
	REG_SPI_DATA = 0;
	WAIT_FOR_NOT_BUSY();
	result = REG_SPI_DATA;

	// Clock in the rest of the data (last transfer)
	REG_SPI_CR = SPI_ENABLE | SPI_SINGLE | SPI_TOUCH | SPI_8CLOCKS | SPI_2MHZ ;
	REG_SPI_DATA = 0;
	WAIT_FOR_NOT_BUSY();

	// Return the result
	result = ((result & 0x7F) << 5) | (REG_SPI_DATA >> 3);

	REG_SPI_CR = 0;

	return result ;
}

// Code from devkitpro/libnds/source/arm7/touch.c
//---------------------------------------------------------------------------------
signed int touch_read_value(int measure, int retry , int range) {
//---------------------------------------------------------------------------------
	int i;
	signed int this_value=0, this_range;

	signed int last_value = touch_read(measure | 1);

	for ( i=0; i < retry; i++) {
		this_value = touch_read(measure | 1);
		if ((last_value - this_value) > 0)
			this_range = last_value - this_value;
		else
			this_range = this_value - last_value;
		if (this_range <= range) break;
	}

	if ( i == range) this_value = 0;
	return this_value;
}

unsigned char power_read(enum power_reg reg)
{
	unsigned char val;

	WAIT_FOR_NOT_BUSY();

	REG_SPI_CR = SPI_ENABLE | SPI_CONTINUOUS | SPI_POWER | SPI_8CLOCKS | SPI_1MHZ ;
	REG_SPI_DATA = POWER_READ | reg ;

	WAIT_FOR_NOT_BUSY();

	REG_SPI_CR = SPI_ENABLE | SPI_SINGLE | SPI_POWER | SPI_8CLOCKS | SPI_1MHZ ;
	REG_SPI_DATA = 0x0;

	WAIT_FOR_NOT_BUSY();

	val = REG_SPI_DATA ;

	REG_SPI_CR = 0 ;

	return val;
}

void power_write( enum power_reg reg, unsigned char val )
{
	WAIT_FOR_NOT_BUSY();

	// Write the command and wait for it to complete
	REG_SPI_CR = SPI_ENABLE | SPI_CONTINUOUS | SPI_POWER | SPI_8CLOCKS | SPI_1MHZ ;
	REG_SPI_DATA = POWER_WRITE | reg ;

	WAIT_FOR_NOT_BUSY();

	// Write the data
	REG_SPI_CR = SPI_ENABLE | SPI_SINGLE | SPI_POWER | SPI_8CLOCKS | SPI_1MHZ ;
	REG_SPI_DATA = val;

	REG_SPI_CR = 0 ;
}

void read_firmware(unsigned int address, unsigned char * destination, int count)
{
	int i;

	WAIT_FOR_NOT_BUSY();

	REG_SPI_CR = SPI_ENABLE | SPI_CONTINUOUS | SPI_FIRMWARE | SPI_8CLOCKS | SPI_4MHZ ;
	REG_SPI_DATA = 3;
	WAIT_FOR_NOT_BUSY();

	REG_SPI_DATA = (address >> 16) & 255;
	WAIT_FOR_NOT_BUSY();

	REG_SPI_DATA = (address >> 8) & 255;
	WAIT_FOR_NOT_BUSY();

	REG_SPI_DATA = (address) & 255;
	WAIT_FOR_NOT_BUSY();

	for (i = 0; i < count; i++) {
		REG_SPI_DATA = 0;
		WAIT_FOR_NOT_BUSY();

		destination[i] = REG_SPI_DATA;
	}

	REG_SPI_CR = 0;
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -