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

📄 cs8900a.c.bak

📁 嵌入式三星2410板子上实现通信服务。共分为接收端和发送端两部分
💻 BAK
字号:
#include "cs8900a.h"
#include "2410lib.h"
#include <string.h>

#define IO_BASE		0x19000300 //IO映射基地址
#define MAX_COUNT	0x00100000 //发送检查芯片状态时,等到的最大循环数

#define MAX_LENGTH 1536
//mac地址,从高位到低位,索引从小变大.
unsigned char mac_addr_src[6] = { 0x01,0x02,0x03,0x04,0x05,0x06};
unsigned char mac_addr_des[6] = { 0x01,0x02,0x03,0x04,0x05,0x07};

#define DA	mac_addr_des
#define SA	mac_addr_src

#define io_write(addr, val)	(*(volatile unsigned short *)(addr) = val)
#define io_read(addr)		((unsigned short)*(volatile unsigned short *)(addr))

inline void reg_write(unsigned short reg, unsigned short val)
{
	io_write(IO_BASE+IO_PACKETPAGE_POINTER, reg);
	io_write(IO_BASE+IO_PACKETPAGE_DATA0, val);
}

inline unsigned short reg_read(unsigned short reg)
{
	io_write(IO_BASE+IO_PACKETPAGE_POINTER, reg);
	return io_read(IO_BASE+IO_PACKETPAGE_DATA0);
}

set_mac_addr(unsigned char *mac)
{
	reg_write(REG_IA, *(unsigned short *)(mac));
	reg_write(REG_IA+2, *(unsigned short *)(mac+2));
	reg_write(REG_IA+4, *(unsigned short *)(mac+4));
}

void cs_init()
{
	unsigned short temp;

	//配置 LineCTL ,cs8900a 数据手册的 p62
	temp = reg_read(REG_LineCTL);
	//8和9位清零,选择10BASE-T only
	temp &= ~(AUIonly | AutoAUI_10BT);
	//设置接受使能、发送使能、使用扩展的back off(退避,即发生冲突时的强制性重传延迟)算法
	temp |= (SerRxON | SerTxON | ModBackOffE);
	//把修改之后的寄存器的值更新。
	reg_write(REG_LineCTL, temp);

	//配置 RxCTL(接收控制寄存器),cs8900a 数据手册的 p54
	//RxOKA:当被设置后,cs8900a接受有正确的CRC校验和合法长度(64B-1518B)的帧
	//IdividualA:当被设置后,只接受目的地址(DA)和REG_IA(地址过滤寄存器,即之前设置的mac地址)相匹配的帧
	//BroadcastA:接受地址为FFFF FFFF FFFF的帧,即接受广播消息
	//RxCTL_LOW:0x05,用来标识这个寄存器的编号。
	reg_write(REG_RxCTL, RxOKA | IdividualA | BroadcastA | RxCTL_LOW);

	//配置 RxCFG (接收配置寄存器),cs8900a 数据手册的 p52
	//如果配置RxOKiE[8]位为1,则收到一个正确的数据包之后,会产生一个RxOK的中断。这里使用查询方式
	//RxCFG_LOW:0x04,RxCFG 芯片的内部编号,用来标识这个寄存器
	reg_write(REG_RxCFG, RxCFG_LOW);

	//配置 TxCFG (传送配置寄存器),cs8900a 数据手册的 p55
	//TxCFG_LOW: 0x07, 芯片内部标号,用来标识这个寄存器
	reg_write(REG_TxCFG, TxCFG_LOW);	
}

//发送函数
//frame_data:发送数据的缓冲区,一帧数据
//length:发送数据(DA-data)的长度
int cs_transmit(unsigned char *frame_data, unsigned length)
{
	int i;
	unsigned short *buf;
  
  //传送命令状态寄存器,cs8900a 数据手册的 p57
  //TxStart: (3<<6),在一个完整的帧(即全部数据)写入缓冲区之后,再开始传送。
  //TxCMD_LOW:芯片内部的该寄存器标识
  io_write(IO_BASE+IO_TX_COMMAND, TxStart | TxCMD_LOW);
  //数据长度寄存器,写入待发送数据长度
  io_write(IO_BASE+IO_TX_LENGTH, (unsigned short)length);	
  
  // 检测芯片可以发送 
	for(i = 0; i < MAX_COUNT; i++)
	{
		//REG_BusST:总线状态寄存器,cs8900a 数据手册的 p67
		unsigned short temp = reg_read(REG_BusST);
		//Rdy4TxNOW:[8]位,如果芯片准备好接受一个帧,则设置该位为1,但是不会产生中断,适合轮询方式
		if(temp & Rdy4TxNOW) break;
	} 

	//如果等待时间超过了预设的最大值,则返回1
	if(i >= MAX_COUNT)
		return 1;

	//往IO_RX_TX_DATA0指向的缓冲区以半字为单位,依次写入要发送的数据
	buf = (unsigned short *)frame_data;
	for(i=0; i<length; i+=2)
		io_write(IO_BASE+IO_RX_TX_DATA0, *buf++);
	
	//返回实际发送的数据
	return 0;
}

//接收函数
//tms:接收的等待时间
//frame_data:接收数据的缓冲区,一帧的数据
//返回值是收到数据的长度,如果为0,则表示超时没有收到数据
int cs_receive(unsigned char *frame_data, unsigned int tms)
{
	int i, length;
	unsigned short *buf;
	unsigned short temp;

	tms *= 50;
	while(tms)
	{
		//unsigned short temp = reg_read(REG_ISQ);读取从而抛弃??
		//REG_RxEvent:接收事件寄存器,cs8900a 数据手册的 p53
		temp = reg_read(REG_RxEvent);
		//RxOK:如果被设置,说明收到了一帧(通过CRC校验,并且长度合法)
		//如果RxOKiE (Register 3, RxCFG, Bit 8)也被设置,则会同时有一个中断,但这里是轮询方式
		if(temp & RxOK) break;
		tms --;
	}

	if(tms == 0)
		return 0;

	// 抛弃 RxStatus 
	reg_read(REG_RxStatus);
	// 读取帧的长度	
	length = reg_read(REG_RxLength);

	// 从IO_RX_TX_DATA0中,读取一帧数据。注意这里读取的是一帧一帧的数据,不包括前导和帧开始标志
	buf = (unsigned short *)frame_data;
	for(i=0; i<length; i+=2)
		*buf++ = io_read(IO_BASE+IO_RX_TX_DATA0);

	//返回读取的长度
	return length;
}

//构建一帧
int cs_construct_frame(unsigned char *orig_data, unsigned char *frame_data)
{
	int i;
	unsigned char *frame_p;
	unsinged short length;
	unsigned short pad_length = 0;
	
	frame_p = frame_data;
	length = strlen(pString);
	
	//检测数据长度是否合法
	if(length > 1518)
	{
		uart_printf("数据长度过长,数据输入非法\n");
		return 0;
	}
	
	//uart_printf("write da\n");
	//DA
	//mac地址的高位放在低地址
	for(i=0; i<6; i++,frame_p++)
		*(frame_p) = DA[i];
	
	//uart_printf("write sa\n");
	//SA
	//mac地址的高位放在低地址	
	for(i=0; i<6; i++,frame_p++)
		*(frame_p) = SA[i];
	
	//uart_printf("write length\n");
	//Length Field
	//length的高位放在高地址处,低位放在低地址处
	*(frame_p) = length;
	
	frame_p += 2;
	
	//uart_printf("write data\n");
	//LLC Data
	for(i=0; i<length; i++,frame_p++)
		*(frame_p) = *(orig_data + i);

	//PR,SD,PAD,FCS这几个数据段不用填充 ,它是由网卡自动产生的
	//Pad(如果数据长度不满46字节,用这段来补齐至少46字节,可以用000000)
	//FCS(可以是CRC或者其他校验方式)
	
	frame_p = NULL;
	return 0;
}

//解析一帧
//返回得到的有效数据的长度
unsigned short cs_parse_frame(unsigned char *frame_data, unsigned char *orig_data)
{
	int i;
	unsigned short length;
	unsigned char *frame_p;

	//因为网卡已经进行了地址过滤和CRC校验,这里直接读取数据就可以了。
	
	//得到数据的长度
	frame_p = frame_data + 14;
	length = *((unsigned short *)frame_p);

	//LLC Data
	//根据长度得到数据
	for(i=0; i<length; i++)
		*(orig_data + i) = *(frame_p + 14 + i);
		
	return length;
}

int test_c8900_transmit(int xpos, int ypos)
{

	unsinged char frame_senddata[100]={0};
	char* pString;
	uart_printf("请输入所要传送的字符\n");
	uart_getstring(pString);
	set_mac_addr(mac_addr_src);
	cs_init();
	ret = cs_construct_frame(pString, frame_senddata);
	if(ret != 0)
	{
		uart_printf("创建数据帧错误");
		return 0;
	}
	ret = cs_transmit(frame_senddata, 14+length);
	if(ret != 0)
	{
		uart_printf("cs_transmit错误!");
		return 1;
	}
	/*int ret;
	int i;
	
	unsigned char senddata[6] = {'3','2','0','2','4','0'};
	unsigned char frame_senddata[24] = {0};

	set_mac_addr(mac_addr);	
	cs_init();
	
	//根据传过来的坐标,构造发送数据
	senddata[0] = (unsigned char)(xpos / 100) + 48;
	senddata[1] = (unsigned char)((xpos % 100) / 10) + 48;
	senddata[2] = (unsigned char)(xpos % 10) + 48;
	senddata[3] = (unsigned char)(ypos / 100) + 48;
	senddata[4] = (unsigned char)((ypos % 100) / 10) + 48;
	senddata[5] = (unsigned char)(ypos % 10) + 48;
	
	ret = cs_construct_frame(senddata, (unsigned short)6, frame_senddata);
	if(ret != 0)
	{
		uart_printf("cs_construct_frame error!");
		return 1;
	}
	
	//for test
	//for(i=0; i<24; i++)
		//uart_printf("frame_senddata %d is %4x\n",i, frame_senddata[i]);
		
	ret = cs_transmit(frame_senddata, 20);
	if(ret != 0)
	{
		uart_printf("cs_transmit error!");
		return 1;
	}
	uart_printf("data(%d,%d) has been transmited\n",xpos, ypos);
	return 0;*/
}

⌨️ 快捷键说明

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