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

📄 spi.c

📁 用LPC936实现通过SPI扩展多个串口,在这里实现了对多个通道的管理,C代码,
💻 C
字号:
#include "uart.h"
#include "spi.h"
#include <intrins.h>

Queue idata spi_tx_queue[MAX_NUMBER];
unsigned char xdata spi_tx_buffer[MAX_NUMBER][SPI_TX_BUF_SIZE];
Queue idata spi_rx_queue[MAX_NUMBER];
unsigned char xdata spi_rx_buffer[MAX_NUMBER][SPI_RX_BUF_SIZE];
Queue idata spi_mtx_queue[MAX_NUMBER];
unsigned char xdata spi_mtx_buffer[MAX_NUMBER][SPI_MTX_BUF_SIZE];

unsigned char back_buffer[MAX_NUMBER];
bit back_buffer_type_0=0;
bit back_buffer_type_1=0;
bit data_ready_0=0;
bit data_ready_1=0;

bit spi_tx_rx_disable_0=0;
bit spi_tx_tx_disable_0=0;
bit spi_rx_rx_disable_0=0;
bit spi_rx_tx_disable_0=0;
bit spi_rx_flag_0=0;
bit spi_tx_flag_0=0;
bit spi_exist_0=0;
bit spi_infor_status_0=1;
bit spi_uart_status_0=0;
bit spi_uart_ack_0=0;
bit spi_equip_exist_0=0;
bit spi_query_fin_0=0;
bit spi_query_status_0=0;

bit spi_tx_rx_disable_1=0;
bit spi_tx_tx_disable_1=0;
bit spi_rx_rx_disable_1=0;
bit spi_rx_tx_disable_1=0;
bit spi_rx_flag_1=0;
bit spi_tx_flag_1=0;
bit spi_exist_1=0;
bit spi_infor_status_1=1;
bit spi_uart_status_1=0;
bit spi_uart_ack_1=0;
bit spi_equip_exist_1=0;
bit spi_query_fin_1=0;
bit spi_query_status_1=0;

char cur_index=0;

bit spi_busy=0;
bit dsr_rec=0;

unsigned char data order_buffer[MAX_ORDER_NUMBER];
char order_length=0;
bit  order_busy=0;

bit spi_msg_dispatch(void);
void spi_return_ack(void);
void spi_get_msg(void);

int init_spi(void)
{
	int i;
	
	for(i=0;i<MAX_NUMBER;i++){
		queue_init(spi_tx_queue[i],spi_tx_buffer[i],SPI_TX_BUF_SIZE);
		queue_init(spi_rx_queue[i],spi_rx_buffer[i],SPI_RX_BUF_SIZE);
		queue_init(spi_mtx_queue[i],spi_mtx_buffer[i],SPI_MTX_BUF_SIZE);
		back_buffer[i] = NUL;
		w_spi_tx_rx_disable(i,0);
		w_spi_tx_tx_disable(i,0);
		w_spi_rx_rx_disable(i,0);
		w_spi_rx_tx_disable(i,0);
		w_spi_rx_flag(i,0);
		w_spi_tx_flag(i,0);
		w_spi_exist(i,0);
		w_spi_infor(i,1);
		w_spi_uart_status(i,0);
		w_spi_uart_ack(i,0);
		w_spi_equip_exist(i,0);
		w_spi_query_fin(i,0);
		w_spi_query_status(i,0);
	}
	
	spi_busy = 0;
	cur_index = 0;

	SPCTL = 0xD4;
	SPSTAT = 0xC0;
	ESPI = 1;
}

void spi_return_ack(void)
{
	char i;
	char c;
	bit b1,b2;

	if(dsr_rec != DSR){
		if(DSR){
			w_spi_infor(0,1);
			w_spi_infor(1,1);
			w_spi_query_fin(0,0);
			w_spi_query_fin(1,0);
		}
		dsr_rec = DSR;
	}	

	for(i=0;i<MAX_NUMBER;i++){
		b1 = spi_query_fin(i);
		if((!b1) && (!order_busy)){
			order_buffer[0] = '0' + i;
			order_buffer[1] = QUERY;
			order_buffer[7] = 1;
			if(spi_send_msg(order_buffer)){
				w_spi_query_fin(i,1);
			}
		}
		
		b1 = spi_uart_ack(i);
		if(b1){
			if(queue_unused(mtx_queue) > 4){
				send_msg(MSG_EOF_FLAG);
				send_msg(i+'0');
				b2 = spi_uart_status(i);
				if(b2) c = ACK_O;
				else c = ACK_C;
				send_msg(c);
				send_msg(MSG_EOF_FLAG);
				w_spi_uart_ack(i,0);
			}
		}

		b1 = spi_query_status(i);
		if(b1){
			if(queue_unused(mtx_queue) > 4){
				send_msg(MSG_EOF_FLAG);
				send_msg(i+'0');
				b2 = spi_equip_exist(i);
				if(b2) c = DEXIST;
				else c = DNONEXIST;
				send_msg(c);
				send_msg(MSG_EOF_FLAG);
				w_spi_query_status(i,0);
			}
		}

		b1 = spi_infor(i);
		if(b1){
			if(queue_unused(mtx_queue) > 4){
				send_msg(MSG_EOF_FLAG);
				send_msg(i+'0');
				b2 = spi_exist(i);
				if(b2) c = EXIST;
				else c = NONEXIST;
				send_msg(c);
				send_msg(MSG_EOF_FLAG);
				w_spi_infor(i,0);
			}
		}
	}

}

void spi_get_msg(void)
{
	int c;

	while(1){
		if(!order_busy){
			if((c = get_msg()) != -1){
				if(c==FLAG){
					if(order_length>=2){
						if(order_buffer[0]-'0' < MAX_NUMBER) order_busy = 1;
						else order_length = 0;	
					}
				}else{
					order_buffer[order_length]=c;
					order_length=(order_length+1)%MAX_ORDER_NUMBER;
				}
			}else return;
		}else if(!spi_msg_dispatch()) return;
	}
}

bit spi_msg_dispatch(void)
{
	if(order_busy){
		switch(order_buffer[1]){
		case XON:
		w_spi_rx_rx_disable(order_buffer[0]-'0',0);
		order_busy = 0;
		order_length = 0;
		break;
		case XOFF:
		w_spi_rx_rx_disable(order_buffer[0]-'0',1);
		order_busy = 0;
		order_length = 0;
		break;
		case FW_ENABLE:
		case FW_DISABLE:
		case DR_ENABLE:
		case DR_DISABLE:
		case CLOSE_UART:
		order_buffer[MAX_ORDER_NUMBER-1]=1;
		if(spi_send_msg(order_buffer)){
			order_length = 0; 
			order_busy = 0;
		}else return 0;
		break;
		case OPEN_UART:
		order_buffer[MAX_ORDER_NUMBER-1]=2;
		if(spi_send_msg(order_buffer)){
			order_busy = 0;
			order_length = 0;
		}else return 0;
		break;
		default:
		order_busy = 0;
		order_length = 0;
		return 1;
		}
	}

	return 1;
}

bit spi_send_msg(unsigned char data *str)
{
	char i;

	if(str[0]-'0' < MAX_NUMBER){
		if(queue_unused(spi_mtx_queue[str[0]-'0']) > str[MAX_ORDER_NUMBER-1]){
			for(i=0;i<str[7];i++){
				queue_input(&spi_mtx_queue[str[0]-'0'],str[i+1]);
			}
		}else return 0;
	}
	return 1;
}

void spi_send_data(void)
{
	int i,c;
	bit b1,b2,b3,b4,b5;

	for(i=0;i<MAX_NUMBER;i++){
		b1 = data_ready(i);
		if(!b1){

			w_back_buffer_type(i,0);
			c = queue_output(&spi_mtx_queue[i]);
			
			if(c==-1){
				b2 = spi_tx_rx_disable(i);
				b3 = spi_exist(i);
				b4 = spi_uart_status(i);
				b5 = spi_equip_exist(i);
				if((!b2) && (b3)
				   && (b4) && b5){
					c = queue_output(&spi_tx_queue[i]);
					w_back_buffer_type(i,1);
				}
			}

			if(c != -1){
				back_buffer[i] = c;
				w_data_ready(i,1);
			}
		}
	}

	if(!spi_busy){
		spi_busy = 1;
		select_spinumber(cur_index);
		b1 = data_ready(cur_index);
		if(b1){
			b2 = back_buffer_type(cur_index);
			if(b2){
				switch(back_buffer[cur_index]){
					case XON:
					case XOFF:
					case FW_ENABLE:
					case FW_DISABLE:
					case DR_ENABLE:
					case DR_DISABLE:
					case OPEN_UART:
					case CLOSE_UART:
					case QUERY:
					case FLAG:
					case NUL:
					back_buffer[cur_index]=back_buffer[cur_index]^XXXX;
					SPDAT=FLAG;
					break;
					default:
					w_data_ready(cur_index,0);
					SPDAT=back_buffer[cur_index];
					break;
					}
			}else{
				w_data_ready(cur_index,0);
				SPDAT = back_buffer[cur_index];
			}
		}else SPDAT = NUL;
	}
}

void spi_scan(void)
{
	spi_get_msg();
	spi_return_ack();
	spi_send_data();				
}

void SPI_INT(void) interrupt 9
{
	char c;
	bit b1,b2;

	SPSTAT = 0xC0;
	c = SPDAT;
	spi_busy = 0;
	
	b1 = spi_rx_flag(cur_index);
	if(b1){
		w_spi_rx_flag(cur_index,0);
		queue_input(&spi_rx_queue[cur_index],c^XXXX);
		b2 = spi_rx_tx_disable(cur_index);
		if(!b2){
			if(queue_high(spi_rx_queue[cur_index])){
				if(queue_input(&spi_mtx_queue[cur_index],XOFF)) 
					w_spi_rx_tx_disable(cur_index,1);
			}
		}
	}else{
		switch(c){
		case NONEXIST:
		w_spi_exist(cur_index,0);
		w_spi_infor(cur_index,1);
		break;
		case EXIST:
		w_spi_exist(cur_index,1);
		w_spi_infor(cur_index,1);
		break;
		case ACK_O:
		w_spi_uart_status(cur_index,1);
		w_spi_uart_ack(cur_index,1);
		break;
		case ACK_C:
		w_spi_uart_status(cur_index,0);
		w_spi_uart_ack(cur_index,1);
		break;
		case XON:
		w_spi_tx_rx_disable(cur_index,0);
		break;
		case XOFF:
		w_spi_tx_rx_disable(cur_index,1);
		break;
		case NUL:
		b2 = spi_rx_tx_disable(cur_index);
		if(b2){
			if(queue_low(spi_rx_queue[cur_index])){
				if(queue_input(&spi_mtx_queue[cur_index],XOFF)) 
					w_spi_rx_tx_disable(cur_index,0);
			}
		}
		break;
		case FLAG:
		w_spi_rx_flag(cur_index,1);
		break;
		case QUERY:		
		w_spi_equip_exist(cur_index,1);
		w_spi_query_status(cur_index,1);
		break;
		default:
		queue_input(&spi_rx_queue[cur_index],c);
		b2 = spi_rx_tx_disable(cur_index);
		if(!b2){
			if(queue_high(spi_rx_queue[cur_index])){
				if(queue_input(&spi_mtx_queue[cur_index],XOFF)) 
					w_spi_rx_tx_disable(cur_index,1);
			}
		}
		break;
		}
	}

	if(cur_index==0) cur_index=1;
	else cur_index=0;

}

⌨️ 快捷键说明

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