文档库 最新最全的文档下载
当前位置:文档库 › 使用C8051F32X带USB接口的单片机_省略_C8051F32X单片机USB

使用C8051F32X带USB接口的单片机_省略_C8051F32X单片机USB

一、USB接口特点、组成及结构

https://www.wendangku.net/doc/8014553302.html,B接口的优点

⑴ 通信速度快:USB1.1规范,全速最高传输速率可达12Mb/s,比串口快100倍;USB2.0规范,可提供480Mb/s 的数据传输速率。

⑵ 支持多个不同设备,可与主机通信,理论上可达127个设备。

⑶ 提供5V/100mA 的电源,使得低功率USB 设备不再需要另接电源。

⑷ 支持热插拔。即PC 在开机状态下,可实现即插即用功能。当插入USB 设备时,主机检测该外设,并通过加载相关驱动程序,对该设备进行配置。

⑸ USB 为所有USB 外设提供单一的、易于操作的连接形式,简化了设备连接方式。

总之,USB 是一种快速、双向、同步传输、廉价、方便使用的可热插拔的串行接口。其快速通信能力可提升各种外设、仪器、自控设备的功能,并使之进入大容量实时图像传输的新时期。正因为如此,USB 接口已成为各种外设、仪器、自控设备发展的一个新方向,并在逐渐取代传统外设。

2.C8051F32×单片机USB接口特点

⑴ 单片机的USB 接口不需外接任何电子元件,就可进行USB 通信。

⑵ 单片机的USB 接口;全速通信速率可达12Mb/s,慢速可达1.5Mb/s.

⑶ 单片机内嵌USB 核,能处理绝大多数USB 事件,大大简化了程序。

⑷ 单片机USB 接口内有一个串行接口引擎(sie),Sie 与USB 的数据线D+、D-相连,在USB 设备与PC 间传送数据。

⑸ 单片机USB 接口带有1KB fifo(先进先出)专用XRAM 区,方便了USB 数据交换。

⑹ C8051F32×单片机有32只引脚,具有8051内核,指令和8051兼容,在同类带USB 接口的单片机产品中,是功能较强、硬件制作和连接最简单,价格较便宜,最便于推广和应用开发的。

3.C8051F32×单片机USB接口和结构

⑴ 组成和结构

单片机内的USB 接口符合USB 2.0规范,在USB1.1全速工作状态下可达12Mb/s,低速状态下为1.5Mb/s。

USB 内部集成了收发器和端点,以及fifo—XRAM,共有8个端点。

一个双向端点(端点0)和3对输入输出端点(端点1~3)。

XRAM 中有1kb 存储空间专用于USB 的fifo,该空间被分配给端点0~3(说明:每个端点所对应的XRAM 地址空间请查看C8051F32×技术说明的相关内容)。

USB 接口内有4倍时钟乘法器和时钟恢复电路,并允许使用内部高精度振荡器作为USB 时钟源,全速时为48MHz。

CPU 内部时钟源和USB 时钟相互独立。USB 接口的收发器符合USB2.0规范,内部

具有上拉电阻和匹配电路,其内部上拉电阻可被软

编者按:目前,带USB 总线的产品越来越多,其优越性也更加显现,USB 的应用必将向着更深和更广的方向发展。为了使读者进一步了解和掌握USB 设计技术,本刊特推出《使用C8051F32X 带USB 接口的单片机进行数据采集和USB 接口通信》系列讲座,以帮助大家掌握利用片内带USB 接口的单片机进行数据采集和用USB 接口进行数据通信的相关技术。使用C8051F32X 带USB 接口的单片机进行数据采集和USB 接口通信(三)

——C8051F32X 单片机USB 数据通信开发

2010 VOL.03

46

件使能/禁止,可根据用户的需求速度设置出现在D+、D-引脚上。

⑵ USB接口连线定义如下:①脚Vbus(电源正),红线;②脚D-(负差分信号),白线;③脚D+(正差分信号),绿线;④脚GND(电源地),黑线。

二、C8051F32×单片机USB接口数据

通信开发过程和实例

https://www.wendangku.net/doc/8014553302.html,B主机和USB设备(指下位机中带USB 接口的单片机)通信过程简述

用户在PC机应用软件上发出的一条通信指令,经应用软件传送到USB的设备驱动程序,在总线上转换成USB的数据流,通过USB电缆传送给USB 下位机设备;下位机中带USB接口的单片机接收并处理指令后,再将处理后的状态和数据结果传回USB主机。

需注意的是,所有的数据传送都是由主机开始的,任何USB外设(即带USB接口的单片机)都无权开始一次传输,也就是说,USB外设是从机。

https://www.wendangku.net/doc/8014553302.html,B驱动软件和专用开发软件包在USB 开发中的作用

为了使数据能在USB总线进行传输,为了便于使用USB接口,USB接口芯片开发商开发了USB接口专用驱动开发软件包。

本实例所用的USB接口专用驱动开发软件包为USB—Xpress的3.11版,其组成和作用如下:

⑴ 上位机USB接口驱动软件

作用:在windows-xp操作系统支持下,对从PC主机到PC的USB接口间的许多层面之间的物理的/信号的/数据包的/进行顺利连接;能够简捷地将有关软件指令转换成USB数据流。该驱动软件需在PC上安装。

⑵ 在上位机应用软件程序的开发编程中,为了高效地开发USB接口程序,将引用专用USB_api 函数库,用若干功能模块来有效开发USB接口部分。USB_api函数库是以一个windows动态链接库的形式出现的。重要的USB动作,将通过调用对应的功能模块来完成。

如:si_open,是打开设备模块;Si_read,是将要从下位设备中读取数据;Si_write,要对下位机设备写入数据。具体的USB_api函数说明,请看有关说明(见附录)。

⑶ 在下位机USB外设(即带USB接口的单片机)的`USB通信软件程序开发中,对于USB接口的重要功能、动作,同样是通过调用USB_api的下位机(下层)函数库中的重要功能函数模块,来高效地开发USB接口部分的程序的。

下面是几个重要的USB_api功能函数模块:

USB_clock_start(); USB接口时钟初始化。

USB_init(); USB接口使能。

USB_int_enable( ); USB中断使能。

USB_api_test_isr( );中断16,判断中断源。

Block_write; 单片机通过USB口写数据到主机。

Block_read; 通过USB口从主机读数据到单片机。

由于C8051F32×单片机在USB口通信软件开发中使用了USBxpress软件包,大大缩短了软件开发时间,简化了开发过程。所以,了解和掌握该软件包的使用,是开发USB接口的关键。

3.单片机端USB-API函数库说明

⑴ USB_Clock_Start

功能:初始化USB总线时钟。包括使能内部振荡器、初始化时钟倍频器,以及设置USB时钟为48MHz,以便USB全速工作。此功能必须在调用USB_Init函数或访问任何可变的XRAM高1024字节(USB时钟范围)之前调用。

说明:在调用USB_Clock_Start或USB_Init函数之后不应该修改的特殊功能寄存器

1)不应该修改的USB特殊功能寄存器有:USB0XCN、USB0ADR和USB0DAT。

2)不应该修改的其他特殊功能寄存器有:CLKMUL、OSCICN的5~7位、CLKSEL的4~6位,即用于使能内部振荡器、建立4倍频时钟为48MHz,以及将该时钟作为USB模块的时钟的特殊功能寄存器。为确保API的正常运行,它们不得被修改。

47电子制作

API用户共享特殊功能寄存器:特殊功能寄存器CLKSEL用于系统时钟源和USB时钟源的选择。需要注意的是:在为获得所需系统时钟而对其位1~0置位时,要使用或(OR)指令,以免改变其6~4位(即USB时钟选择位)的值。特殊功能寄存器OSCICN用来控制内部振荡器。其IFCN位不会影响12MHz时钟倍频输入或USB时钟,用户可以根据对系统时钟频率的需要对IFCN [1:0]位进行修改。只是在修改IFCN [1:0]位时,应注意保护其5~7位不被改变。

⑵ Block_Write

功能:块写入。即通过USB将单片机缓冲区中的数据传给主机。其最大可传数据块为4096字节。返回的数字是实际写入的字节数。除非错误条件发生,否则应与参数NumBytes完全相符。NumBytes的有效数值为1~4096。如果调用Block_Write,而NumBytes大于4096字节,返回值为零。如果NumBytes大于64字节,所传输得数据将被分成多个数据包,每个数据包64字节(除最后一个数据包外)。在将最后一个数据包复制到设备的USB发送缓冲区后,Block_Write函数返回。

⑶ Block_Read

功能:块读出,即通过USB将主机发来的数据读到单片机的缓冲区中。其最大可接收的数据块为64字节。返回时,无论全部缓冲区是否被Block_Read函数读取过,器件的USB接收缓冲区都将清空。从器件的USB接收缓冲区读取的最大字节数由NumBytes指定。实际读取的字节数(即复制到缓冲区的字节数)由函数返回。如果没有要读取的字节,返回零。通常,Block_Read 函数是在接收一个数据包后被调用,由RX_COMPLETE USB API中断指示。

当发送到SI_Write的缓冲区大于64字节,则通过一次SI_Write函数调用传送的数据,将需要多次调用Block_Read函数来读取。

⑷ Get_Interrupt_Source

功能:获取中断源,即返回一个表示USB-API中断源的8位数,同时清除USB-API待处理中断标志。Get_Interrupt_Source函数应在用户中断服务程序开始时调用,以判定发生了哪些事件。

返回值编码如下:

0x00 没有USB API中断

0x01 USB_RESET USB复位中断

0x02 TX_COMPLETE 发送完成中断

0x04 RX_COMPLETE 接收完成中断

0x08 FIFO_PURGE 命令接收(从主机服务)清除的USB缓冲区

0x10 DEVICE_OPEN 器件打开在主机端

0x20 DEVICE_CLOSE 器件关闭在主机

0x40 DEV_CONFIGURED 器件已进入配置状态

0x80 DEV_SUSPEND 在暂停的USB总线上信号

⑸ USB_Int_Enable

功能:允许USB API中断。调用USB_Int_ Enable函数后,下述API事件均可产生USB API 中断。

1)发生USB复位。

2)一个调用Block_Write(块写入)函数的传送完成。

3)收发缓冲区已准备好为调用Block_Read(块读出)服务。

4)来自主机的命令使USB缓冲区被刷新。

5)设备实例已被主机打开或关闭。

USB API的中断源,可以通过调用Get_ Interrupt_Source 函数得到。如果USB API中断被允许,用户必须提供一个中断服务程序,其程序入口为中断向量16(地址=0x0083)。当此函数被调用时,如果已有任何USB API中断申请,则在1毫秒内程序会响应该中断,进入中断16处理程序。

4. 单片机通过USB口将数据块上传给PC 机的实例

(1)实例介绍

本实例所用的上位机软件界面,如图1所示。

1)最上面的对话框:在将单片机USB接口和PC机的USB接口连接好,并运行上位机软件,且与单片机USB口握手成功后,框内将显示:1 2 3 4;

2)软件的最下面的对话框(RECEIVE FILE)是:PC机接收来自单片机的数据块(存成.hex文件),

2010 VOL.03 48

操作时,先点击BROWSE,选好存储介质,写入.hex 文件名;再点击左边(RECEIVE FILE)框,便把来自单片机的数据存到PC 机的对应.hex 文件中了。

图1

⑵ 用单片机的USB 口将数据传送到PC 的程序流程图

图2是单片机端的USB 数据通信程序流程图。程序是用C51编的。程序中大量调用了USB_API 函数库中的重要功能函数模块,使用的编译器是keil—8.08。

(3)单片机端USB 接口数据上传程序说明这个例程:能实现,将c8051f320单片机内的flash 程序区内的,从2000h 起存放的数据块;通过usb 接口上传到pc 端。通过pc 端的应用接收软件,将数据块存成hex 数据文件。并存放到pc 的硬盘中。一次最大的数据块存储量;是4kb.具体的例程演示和操做,可查看320usb 单片机开发板使用说明。

1)运行上位机软件、上下位机USB 接口连接好,USB 初始化后。上位机软件得到下位机的状态回应(设备已准备好),此时,上位机软件对话框(SELECT)中显示1 2 3 4,表示上下位机USB 接口初始化完成,握手成功。

此时,单片机端的程序为:

调用USB-API 函数:USB_clock_start();USB 时钟初始化,内部时钟12MHz,USBq 全速时钟48MHz ;port1_init();i/o 接口初始化;

调用USB-API 函数:USB_init();USB 接口使能;调用USB-API 函数:

USB_int_enable();USB

图2

usb_cloch_start();USB 时钟初始化usb_init();USB 接口使能

Port1_init();I/O 口初始化Usb_int_enable();USB 中断使能

While(i)等待

Usb_api_test_isp(),interrupt16;中断16为指示中断原因函数;运行usb_api 中断,进入中断服务程序

判中断类型,置当前状态m_stara=;进入state_machine()函数

如USB 设备已打开,接收主机设置信息RECEIRE_SETUP();

block_read 函数读主机所发设置信息(buffer3)

buffer(0)=read_msg ?是执行下一步,否转PC 发数据

设置上传数据块指针、字节长度、地址及数据变量

设置状态m_state=st_tx_file Led2=1灯亮;

进入state_machine()函数,转St_tx_file 模块(数据块发主机)

设传送长度,调block_write 函数确认数据指针,写入指针,确认变量

写数据块到PC,LED2闪

数据块写完?写完led2=0灯灭,传送结束

49

电子制作

中断使能。

2)在上位机软件进行数据块上传操作时,点击左下角对话框(RECEIVE FILE),上位机发出将单片机内数据上传的命令,通过USB口将命令设置信息下载到单片机的buffer中。此时,单片机端程序运行状态为:进入中断16的中断服务程序。

USB_api_test_isr();指示中断原因,设置当时状态。之后,进入state_machine()函数,由于USB上下位机设备都已打开,程序进入接收主机设置信息函数RECEIVE_SETUP(),并用block_ read;USB-api函数,读PC发送的命令设置,---(buffer 3),并判断buffer(0)是否=read_msg.

如成立,则进入单片机数据发送到PC的准备程序。

这段程序的功能是:a)将变量(数据块) numblock,确认;发送的数据块起始地址。数据块在在单片机flash的2000h~21ffh中; b)确定变量(数据块)的最大个发送字节。 c)调用block_ write,USB_api函数,把上述设置信息发送到主机,即Byteswrote=block_write(byte*)&buffer;

同时,将此时的状态设置为:m_state_=st_tx_ file;并点亮led2=1,发光管。

3)程序再次进入state_machine()函数,此时状态设置为:

到tx_file单片机数据发送至PC模块,程序完成下面动作,a) 设要写的数据长度和数据块的起始地址。 b)调用USB_api功能函数block_write进行数据发送。C)检查数据是否发送完毕?发送时,led2在闪动;发送完毕,led2熄灭。

(4)单片机端USB接口数据上传源程序

该源程序采用C语言编制,用C51的keil—8.08编译器编译,文件名:USBsvg.c。程序中大量使用了USB_api单片机端的函数库。所以在编译中,必须连接库文件,即USBx_f320_1.lib库文件。

源文件如下:

//包含文件

#include

// C8051F320头文件

#include

// NULL指针定义

#include "USB_API.h"

// USB_API.lib头文件

//位定义

Sbit Led1=P2^2;

// P2.2置1,点亮LED1

Sbit Led2=P2^3;

// P2.3置1,点亮LED2,指示数据传送

//常量定义

#define NUM_STG_PAGES 20

//定义文件存储的flash 总页数为20

#define MAX_BLOCK_SIZE_READ 64

//读数据块的最大字节数为64

#define MAX_BLOCK_SIZE_WRITE 4096

//写数据块的最大字节数为4096

#define FLASH_PAGE_SIZE 512

//每个flash页为512

#define BLOCKS_PR_PAGE FLASH_PAGE_ SIZE/MAX_BLOCK_SIZE_READ

// 512/64 = 8

#define MAX_NUM_BYTES FLASH_PAGE_ SIZE*NUM_STG_PAGES

#define MAX_NUM_BLOCKS BLOCKS_PR_ PAGE*NUM_STG_PAGES

//信息类型

#define READ_MSG 0x00

//主机通信信息类型

#define WRITE_MSG 0x01

#define SIZE_MSG 0x02

#define DELAYED_READ_MSG 0x05

//机器状态

#define ST_WAIT_DEV 0x01

//等待应用程序打开设备

#define ST_IDLE_DEV 0x02

//设备打开,等待主机发设置信息

#define ST_RX_SETUP 0x04

//收到设置信息,解码并等待接收数据

#define ST_RX_FILE 0x08

//接收主机所发数据文件

#define ST_TX_FILE 0x10

//发送数据文件给主机

2010 VOL.03 50

#define ST_TX_ACK 0x20

//处理8个数据包,发一次应答ACK 0xFF给主机

#define ST_ERROR 0x80

//出错状态

// No such thing as a block of data anymore since it is variable between 1 and 1024

// So comment this out

typedef struct { //数据块结构定义

BYTE Piece[MAX_BLOCK_SIZE_READ];

} BLOCK;

typedef struct { // flash存储器页结构定义

BYTE FlashPage[FLASH_PAGE_SIZE];

} PAGE;

Xdata BLOCK TempStorage[BLOCKS_PR_ PAGE];

// Temporary storage of between flash writes

//data B Y T E c o d e* PageIndices[20] = {0x1400,0x1600,0x1800,0x 1A00,0x1C00,0x1E00,0x2000,0x2200,0x2400,0 x2600

// ,0x2800,0x2A00,0x2C00,0x2E00,0x3000,0x 3200,0x3400,0x3600,0x3800,0x3A00};

Data BYTE code * PageIndices[20] = {0x 2000,0x2200,0x2400,0x2600,0x2800,0x2A00,0x2 C00,0x2E00,0x3000,0x3200,0x3400};

data UINT BytesToRead;

//从主机读入的总字节数

data UINT WriteStageLength;

//当前写传送状态长度

data UINT ReadStageLength;

//当前读传送状态长度

data BYTE Buffer[3];

// 设置信息缓冲区

data UINT NumBytes;

// 传送块数

data BYTE NumBlocks;

data UINT BytesRead;

//读字节数

data BYTE M_State;

//机器当前状态

data UINT BytesWrote;

//接字节数

data BYTE BlockIndex;

//当前块在页内的指针

data BYTE PageIndex;

//当前页在文件中的指针

data BYTE BlocksWrote;

//被写块的总数

data BYTE* ReadIndex;

data UINT BytesToWrite;

/ [开始] USB信息描述 [开始] /

code const UINT USB_VID = 0x10C4;

code const UINT USB_PID = 0xEA61;

code const BYTE USB_MfrStr[] = {0x 1A,0x03,'S',0,'i',0,'l',0,'i',0,'c',0,'o',0,'n',0,' ',0,'L',0,'a',0,'b',0,'s',0}; //生产厂

code const BYTE USB_ProductStr[] = {0x10,0x03,'U',0,'S',0,'B',0,' ',0,'A',0,'P',0,'I',0};

//产品描述

code const BYTE USB_SerialStr[] = {0x0A,0x 03,'1',0,'2',0,'3',0,'4',0};

code const BYTE USB_MaxPower = 15;

// 最大电流30mA(15 * 2)

code const BYTE USB_PwAttributes = 0x80;

// 总线电源,不支持远程唤醒

code const UINT USB_bcdDevice = 0x0100;

// 设备版本号1.00

/ [结束] USB信息描述 [结束] /

Code BYTE LengthFile[3] _at_ 0x2000;

// {Length(Low Byte), Length(High Byte), Number of Blocks}

Void Port_Init(void);

// 口初始化并允许交叉

Void State_Machine(void);

// 确定新状态及执行当前状态

Void Receive_Setup(void);

// 接收并解码主机所发设置包

//主程序

void main(void)

51电子制作

{

PCA0MD &= ~0x40;

//看门狗禁止

USB_Clock_Start();

//使能USB口前,先初始化USB时钟

U S B_I n i t(U S B_V I D,U S B_P I D,U S B_ MfrStr,USB_ProductStr,USB_SerialStr,USB_ MaxPower,USB_PwAttributes,USB_bcdDevice);

CLKSEL|=0x02;

RSTSRC|=0x02;

Port_Init();

//I/O口初始化

USB_Int_Enable();

//开USB_API中断

while (1);

}

void Port_Init(void)

{

P2MDOUT |= 0x0C;

//P2.0、P2.1置为高阻态

XBR0=0x00;

XBR1=0x40;//允许交叉

}

Void State_Machine(void)

{

switch (M_State)

{

Case ST_RX_SETUP:

Receive_Setup();

//接收并解码主机所发设置信息

break;

case ST_RX_FILE:

Receive_File(); //接收主机数据文件

break;

case ST_TX_ACK:

M_State=ST_RX_FILE;

//Ack发送完成,继续接收数据

break;

case ST_TX_FILE:

// 发送数据文件到主机

W r i t e S t a g e L e n g t h=((B y t e s T o W r i t e-BytesWrote)>MAX_BLOCK_SIZE_WRITE)? MAX_BLOCK_SIZE_WRITE:(BytesToWrite - BytesWrote);

BytesWrote += Block_Write((BYTE*) (ReadIndex), WriteStageLength);

ReadIndex += WriteStageLength;

If ((BlocksWrote%8)==0)Led2=~Led2;

If (BytesWrote == NumBytes) Led2=0;

break;

default:

break;

}

}

//当API中断允许且收到一个中断申请时,执行USB_API中断

void USB_API_TEST_ISR(void) interrupt 16

{

BYTE INTVAL=Get_Interrupt_Source();

// 确定API中断类型

If (INTVAL&USB_RESET)

// 是总线复位,转等待状态

{

M_State=ST_WAIT_DEV;

}

If (INTVAL&DEVICE_OPEN)

//主机端设备打开,转Idle

{

M_State=ST_IDLE_DEV;

}

if (INTVAL&TX_COMPLETE)

{

If (M_State==ST_RX_FILE)

//应答Ack传完,转RX状态

{

M_State=(ST_TX_ACK);

}

If (M_State == ST_TX_FILE)

//文件块传完,转TX状态

{

2010 VOL.03 52

M_State=(BytesWrote == BytesToWrite) ? ST_IDLE_DEV :ST_TX_FILE;//执行完,转Idle }

}

if (INTVAL & RX_COMPLETE)

// RX完,转RX设置或RX文件状态

{

M_State=(M_State==ST_IDLE_DEV)?ST_RX_ SETUP:ST_RX_FILE;

}

If (INTVAL&DEVICE_CLOSE)

//关设备,等待再次打开

{

M_State=ST_WAIT_DEV;

}

if (INTVAL&FIFO_PURGE)

//清Fifo,转Idle状态

{

M_State=ST_IDLE_DEV;

}

State_Machine(); //调用状态机程序

}

void Receive_Setup(void)

{

BytesRead=Block_Read(&Buffer,3);

//读设置信息

if (Buffer[0]==READ_MSG)

//读文件已设置,选See

{

PageIndex=0; // 指针复位

NumBlocks=LengthFile[2];

//从flash stg读NumBlocks

NumBlocks=(NumBlocks > MAX_NUM_ BLOCKS)? MAX_NUM_BLOCKS: NumBlocks;

//多字节写

// as we have space available

Buffer[0]=SIZE_MSG;

// 发送主机传送信息长度

Buffer[1]=LengthFile[1];

Buffer[2]=LengthFile[0];

BytesToWrite=Buffer[1] + 256*Buffer[2];

BytesWrote=Block_Write((BYTE*)&Buffer, 3);

M_State=ST_TX_FILE;

//转发送数据状态

BytesWrote=0;

ReadIndex=PageIndices[0];

Led2=1;

}

else //否则为写入设置包

{

BytesToRead=Buffer[1]+256*Buffer[2];

NumBlocks=(BYTE)(BytesToRead/MAX_ BLOCK_SIZE_READ);

//Find NumBlocks

if (BytesToRead > MAX_NUM_BYTES)

//传输数据太大,出错

{

M_State = ST_ERROR;

}

else

{

If (BytesToRead%MAX_BLOCK_SIZE_READ) NumBlocks++;

// NumBlocks加1

TempStorage->Piece[0]=Buffer[2];

TempStorage->Piece[1]=Buffer[1];

TempStorage->Piece[2]=NumBlocks;

//Write Values to Flash

//Store file data to flash

PageIndex= 0;

// Reset Index

BlockIndex= 0;

BytesRead= 0;

Led1=1;

M_State=ST_RX_FILE;//转接收数据状态

}

}

}

程序结束;

53电子制作

相关文档
相关文档 最新文档