CS8900A应用笔记
在8位模式下,操作CS8900需要通过下列8个16位端口。
现在我们要发送81字节长度的帧。,假设CS8900A默认的IO口位置是0x0300。, 【1】 写命令到发送命令端口
将命令0x00c0,在所有字节装入后发送,写入命令端口,TxCMD,位置0x0300+0x0004,。
其中0x0304写入的是低位的0xc0,0x0305写入的是高位的0x00。 【2】 写长度到发送长度端口
将长度数据0x0051,十进制81,写入发送长度端口,TxLength,位置0x0300+0x0006,
其中0x0306写入是低位0x51,0x0307写入的是高位0x00。
【3】 检查是否有足够的空间用于发送
这里主要是通过BusST寄存器的BIT8位,完成这项操作将使用数据包页指针端口
,PacketPage Pointer,和数据包页数据端口,PacketPage Data,。
写入0x0138到数据包页指针端口,PacketPage Pointer,位置0x0300+0x000a,。
然后读取数据包页数据端口,PacketPage Data,位置0x0300+0x000c,的数据。
如果得到的数据BIT8位,Rdy4TxNow,是1的话,就可以向收发数据端口0,Transmit Data
Port 0,写入要发送数据了。
【4】 写入发送数据
第1字节数据写入到0x0300,第2字节写入到0x0301。
第3字节数据写入在0x0300,第4字节写入到0x0301,以此类推。 【5】 发送
当该帧的最后一个字节被写入的时候,芯片会自动开始发送。
控制器通过查询接收事件寄存器的方式来获知是否收到数据帧。
【1】 读取接受状态寄存器的值
RxStatus的数据直接由读取收发数据端口获得。,和RxEvent寄存器的值一样,
注意:先从0x0301读取数据高位,再从0x0300读取数据低位。 【2】 读取接受到的数据帧长度
RxLength数据依然又收发数据端口获得
注意:先从0x0301读取数据高位,再从0x0300读取数据低位。 【3】 读取数据帧内容
先从0x0300读取第一个1字节,再从0x0301读取第2个字节,
然后从0x0300读取第一个3字节,再从0x0301读取第4个字节,直到全部读完。
使用MSP430和网卡连接,外带USB供电和虚拟串口不PC机通讯。
MSP430部分硬件电路图:
使用P3和P5口对CS8900A进行操作,其中P3口中包括4根地址线A0~A3,2根读写控制线nIOR和nIOW;另外2个串口收发线TXD和RXD连接到了USB转串口芯片PL2303HX上,实现单片机和PC机直接通讯。P5口完全是8根数据总线D0~D7。
其他的引出P1口用来实现额外的输入输出口。引出P6实现模拟电压采样。
CS8900A部分和USB部分电路图
从TI的例程中提取CS8900.c和CS8900.h文件。
里面主要引出下列函数供用户使用:
void Init8900(void);
// 初始化网卡芯片
void Write8900(unsigned char Address, unsigned int Data);
// 对指定的端口地址写入一个整数(小端方式)
void WriteFrame8900(unsigned int Data);
// 向发送数据帧端口写入一个整数(小端方式)
// 等同于Write8900(TX_FRAME_PORT, Data)调用
unsigned int Read8900(unsigned char Address);
// 从指定的端口地址读取一个整数(小端方式)
unsigned int ReadFrame8900(void);
// 从接收数据帧端口读取一个整数(小端方式)
// 等同于Read8900(RX_FRAME_PORT)调用
unsigned int ReadHB1ST8900(unsigned char Address);
// 从特殊的的端口地址读取一个整数(小端方式), 例如RxStatus寄存器
// 注意: 其中必须先读取地址(Address+1)为整数高8位, 再读取地址(Address)为低8位 unsigned int ReadFrameBE8900(void);
// 从接收数据帧端口读取一个整数(大端方式), 通常用于读取TCP/IP数据 void CopyToFrame8900(void *Source, unsigned int Size);
// 复制一个指定数组的数据到CS8900的内部缓冲区(对TX_FRAME_PORT端口的连续写) void CopyFromFrame8900(void *Dest, unsigned int Size);
// 从CS8900的内部缓冲区复制数据到单片机(对RX_FRAME_PORT端口的连续读) void DummyReadFrame8900(unsigned int Size);
// 对RX_FRAME_PORT端口的连续读取指定的次数, 但是不返回数据. 空读 void RequestSend(unsigned int FrameSize);
// 请求指定长度的内部缓冲区空间(准备用来发送)
unsigned int Rdy4Tx(void);
// 检查CS8900是否准备好开始发送数据? 其实判断等待总线是否忙
下面测试网卡的接收数据功能
void main(void)
{
Clock_Init(); // 初始化系统时钟, 关闭看门狗
USART0_Init(); // 初始化串口, “38400,N,8,1”, 用来和PC机通讯和监控
Init8900(); // 初始化网卡芯片CS8900A
while(true) // 程序主循环
{
RxTest(); // 检查是否接收到数据
RxData(); // 读取接收到的数据并通过串口显示在PC机上
}
}
其中RxTest()函数内容
// CS8900A的接收数据测试
unsigned int RxIndex; // 累计接收到的数据帧
bool Flg_RxData; //
标志
禁止坐卧标志下载饮用水保护区标志下载桥隧标志图下载上坡路安全标志下载地理标志专用标志下载
: 接收到数据
void RxTest(void)
{
unsigned int ActRxEvent; // CS8900的RxEvent寄存器
// 读取CS8900的接收寄存器
Write8900(ADD_PORT, PP_RxEvent); // point to RxEvent
ActRxEvent = Read8900(DATA_PORT); // read, implied skip of last frame
// 检查是否有接收
if (ActRxEvent & RX_OK)
{
if (ActRxEvent & RX_IA) _NOP(); // 接收到EthIAFrame();
if (ActRxEvent & RX_BROADCAST) Flg_RxData = true; // 接收到广播, 置标志
RxIndex++; // 接收序号++, 监视用
}
}
其中RxData()函数内容如下
// 从CS8900中读取到单片机的RAM
unsigned int RxLength; // 接收到的数据长度 unsigned char RxBuff[1024]; // 全局数组, 保存数据用 void RxData(void)
{
unsigned int RxStatus;
if (Flg_RxData == false) return; // 如果没有接收标志, 则退出函数
// 读取接收帧长度(必须先读高8位)
RxStatus = ReadHB1ST8900(RX_FRAME_PORT); // RxStatus寄存器
RxLength = ReadHB1ST8900(RX_FRAME_PORT); // 数据帧真实长度
// 根据数据帧长度, 从CS8900复制数据到单片机
CopyFromFrame8900(RxBuff, RxLength);
// 发送数据到串口
….
// 清除标志, 准备下次接收
RxLength = 0;
Flg_RxData = false;
}
因为以太网中,最小的数据帧位64字节,小于64字节的帧为坏帧。
在TxCMD寄存器中,有两个位分别为InhibitCRC和TxPadDis。他们的作用如下,手册58页,:
InhibitCRC位=1时,CRC校验将不添加在数据包后面。
TxPadDis位=0时,网卡允许发送一个小于64字节的数据帧。否则网卡会将其补满60字节。
结论,整个测试程序的结果如下图,完成单片机控制的CS8900网卡接收数据帧。
bool Flg_TxData; // 发送标志 unsigned int TxLength = 342; // 发送数据帧的长度 unsigned char const TxBuff[] = {...}; // 发送内容 // 发送数据帧
void TxData(void)
{
// 判断发送标志
if (Flg_TxData == false) return;
//
申请
关于撤销行政处分的申请关于工程延期监理费的申请报告关于减免管理费的申请关于减租申请书的范文关于解除警告处分的申请
发送空间
RequestSend(TxLength);
// 判断发送空间是否准许
if (Rdy4Tx() == READY_FOR_TX_NOW)
{
// 复制数据到网卡
CopyToFrame8900((void *)TxBuff, TxLength);
// 复制完所有数据后, 网卡发送
USART0_String("网卡发送数据帧!");
}
else
{
USART0_String("申请发送缓冲区失败!");
}
Flg_TxData = false;
}