STM32USB使用方法.docx

上传人:b****3 文档编号:5128965 上传时间:2023-05-08 格式:DOCX 页数:40 大小:26.60KB
下载 相关 举报
STM32USB使用方法.docx_第1页
第1页 / 共40页
STM32USB使用方法.docx_第2页
第2页 / 共40页
STM32USB使用方法.docx_第3页
第3页 / 共40页
STM32USB使用方法.docx_第4页
第4页 / 共40页
STM32USB使用方法.docx_第5页
第5页 / 共40页
STM32USB使用方法.docx_第6页
第6页 / 共40页
STM32USB使用方法.docx_第7页
第7页 / 共40页
STM32USB使用方法.docx_第8页
第8页 / 共40页
STM32USB使用方法.docx_第9页
第9页 / 共40页
STM32USB使用方法.docx_第10页
第10页 / 共40页
STM32USB使用方法.docx_第11页
第11页 / 共40页
STM32USB使用方法.docx_第12页
第12页 / 共40页
STM32USB使用方法.docx_第13页
第13页 / 共40页
STM32USB使用方法.docx_第14页
第14页 / 共40页
STM32USB使用方法.docx_第15页
第15页 / 共40页
STM32USB使用方法.docx_第16页
第16页 / 共40页
STM32USB使用方法.docx_第17页
第17页 / 共40页
STM32USB使用方法.docx_第18页
第18页 / 共40页
STM32USB使用方法.docx_第19页
第19页 / 共40页
STM32USB使用方法.docx_第20页
第20页 / 共40页
亲,该文档总共40页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

STM32USB使用方法.docx

《STM32USB使用方法.docx》由会员分享,可在线阅读,更多相关《STM32USB使用方法.docx(40页珍藏版)》请在冰点文库上搜索。

STM32USB使用方法.docx

STM32USB使用方法

STM32-USB使用方法

开发板买的是奋斗mini开发板,芯片是:

STM32F103VET6.如果需要源程序keil4-arm工程,上位机vb。

加qq339396264要程序。

USB开发涉及主机和设备,为了避免开发驱动程序,使用Windows自带的驱动程序。

所以设备枚举成HID类设备。

USB鼠标就是标准的USB-HID设备。

不过操作系统阻止了应用程序直接访问USB鼠标返回的报告。

所以本例使用自定义HID设备。

一来免去了开发驱动程序,二来自定义的HID设备应用程序和设备可以自由收发数据(仅指数据内容)。

本文主要介绍STM32的USB模块的简单使用,不会介绍USB协议。

主要是介绍一下STM32F103的USB模块使用。

USB模块从初始化首先是配置和使能时钟

下面是时钟的初始化:

voidSet_USBClock(void)

{

//RCC_USBCLKSource_PLLCLK_1Div5表示【USB时钟=PLL时钟除以1.5】【72/1.5=48MHz】

RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_1Div5);

RCC_APB1PeriphClockCmd(RCC_APB1Periph_USB,ENABLE);//【使能配置好了的USB时钟】

}

首先系统时钟要设置为72MHz,然后配置USB时钟为48MHz并使能。

然后是配置中断

voidUSB_Interrupts_Config(void)

{

#defineUSB_LP_CAN1_RX0_IRQn20

NVIC_InitTypeDefNVIC_InitStructure;

//【使能USB中断】

NVIC_InitStructure.NVIC_IRQChannel=USB_LP_CAN1_RX0_IRQn;//【USB低优先级中断】

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;

NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;

NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;

NVIC_Init(&NVIC_InitStructure);

}

然后初始化模块的一些寄存器

USART_send_str("USB断开\r\n");

USB_DISCONNECT//这是断开1.5k上拉电阻

delay(0x7AFFFF);//延时一会

USB_CONNECT//使能1.5K上拉电阻

USART_send_str("USB连接\r\n");

DADDR=0x0080;//USB模块使能位。

EF必须置1

CNTR=0x0001;//强制复位

CNTR=0x0000;//退出复位

ISTR=0x0000;//清除可能产生的假中断

CNTR=(I_CTR|I_RESET);//使能一些中断,为了简单这里只使能了【总线复位中断】和【数据正确传输中断】

ISTR=0x0000;//清除可能产生的假中断

自此USB模块初始化完毕。

以后的流程就在USB中断的驱动下执行。

USB中断函数:

voidUSB_LP_CAN1_RX0_IRQHandler(void)

{

u16wIstr;

//USB中断状态寄存器

wIstr=(u16)ISTR;

//【USB复位中断】

if(wIstr&I_RESET)

{

USB_RST_Process();

return;

}

//【正确传输中断】

if(wIstr&I_CTR)

{

USB_CTR_Process();

return;

}

}

在USB中断函数中就是判断中断源,并转向相应的中断服务函数。

USB总线复位后,USB相关的一些寄存器会复位。

在USB总线复位中要配置一下寄存器和数据收发的缓冲区。

程序如下

voidUSB_RST_Process(void)

{

//清除中断

ISTR=(u16)(~I_RESET);//清除ISTR寄存器中断RESET位。

写0清除,写1寄存器位内容不变。

//USART_send_str("【USB】【复】【位】【中】【断】\r\n");

usb_status=0;

//复位处理

DADDR=0x0080;//USB模块使能位。

EF必须置1

BTABLE=0;//复位后默认为0

EP0REG=(u16)(0x0220);//0000001000100000端点0初始化:

控制端点,NAK主机的IN令牌,端点号0

//设置TX/RX起始地址

USB_ADDR0_TX=32;//32-95端点0的发送缓冲区从32开始到95,共64字节

USB_ADDR0_RX=96;//96-159端点0的接收缓冲区从96开始到159,共64字节

//设置端点0接收缓冲区大小:

64Byte

USB_CNT0_RX=0x8400;//1000,0100,0000,0000

//【端点1】

EP1REG=(u16)(0x0621);//0000011000100001端点0初始化:

中断端点,NAK主机的IN令牌,端点号1

//设置TX/RX起始地址

USB_ADDR1_TX=160;//160-223端点1的发送缓冲区从160开始到223,共64字节

USB_ADDR1_RX=224;//224-287端点1的接收缓冲区从224开始到287,共64字节

//设置端点1接收缓冲区大小:

64Byte

USB_CNT1_RX=0x8400;//1000,0100,0000,0000

//设置RXValid.端点0可用于接收

{

u16t=EP0REG;//读出端点0寄存器值

t&=0x8F8F;//1000111110001111由于t位写0不影响原来的值,写1翻转,所以把t位都设置为0

t|=0x8080;//1000000010000000由于w0位写0清除,写1无影响,所以w0位都设置为1

t|=0x3000;//0011000000000000把SRAT_RX[1:

0]设置为1,通过写1翻转来实现。

EP0REG=t;

}

}

下面是正确传输中断

//USB分组正确传输处理

voidUSB_CTR_Process(void)

{

/******************************************【端点0】******************************************/

if((ISTR&0x0F)==0)//端点0

{

if((ISTR&0x10)==0)//in分组

{

//USART_send_str("****************端点0的IN分组发送完成****************\r\n");

if(usb_status==1)

{

usb_status=2;

DADDR=0x80|(usb_addr&0xFF);//设置地址一定要找控制传输的状态完成后写入地址寄存器

//USART_send_str("\r\n【写入地址完成】\r\n");

}

//发送剩余数据

USB_ep0_send();

//清除CTR_TX

{

u16t=EP0REG;

t&=0x8F8F;//1000111110001111把t位都设置为0

t|=0x8080;//1000000010000000把w0位都设置为1

t&=0xFF7F;//1111111101111111把CTR_TX设置为0,清除CTR_RX位

EP0REG=t;

}

}

if(ISTR&0x10)//【OUT】分组or【SETUP】分组

{

u16ep0r=EP0REG;

//清除CTR_RX

{

u16t=EP0REG;

t&=0x8F8F;//1000111110001111把t位都设置为0

t|=0x8080;//1000000010000000把w0位都设置为1

t&=0x7FFF;//0111111111111111把CTR_RX设置为0,清除CTR_RX位

EP0REG=t;

}

if(ep0r&0x0800)//SETUP令牌包

{

//USART_send_str("端点0收到【SETUP】分组\r\n");

//默认控制端点处理——枚举处理

ep0_setup_Process();

memset(USB_rcv_buffer,0x00,sizeof(USB_rcv_buffer));

USB_enable_ep0_rx();

}

else

{

//USART_send_str("控制读传输:

状态阶段\r\n");

USB_read_EP0_buf(USB_rcv_buffer,(u32*)(PMAAddr+96*2));

USB_enable_ep0_rx();

}

}

//else//【IN分组传输成功】

}

/******************************************【端点1】******************************************/

elseif((ISTR&0x0F)==1)

{

USART_send_str("端点1数据完成传输\r\n");

if(ISTR&0x10)//【OUT分组】

{

//清除CTR_RX

{

u16t=EP1REG;

t&=0x8F8F;//1000111110001111把t位都设置为0

t|=0x8080;//1000000010000000把w0位都设置为1

t&=0x7FFF;//0111111111111111把CTR_RX设置为0,清除CTR_RX位

EP1REG=t;

}

USB_read_EP1_buf(USB_rcv_buffer,(u32*)(PMAAddr+224*2));//【读取】端点1数据

//【处理】端点1数据

USB_enable_ep1_rx();//【继续接受】端点1数据

}

else//【IN分组】

{

//清除CTR_TX

{

u16t=EP1REG;

t&=0x8F8F;//1000111110001111把t位都设置为0

t|=0x8080;//1000000010000000把w0位都设置为1

t&=0xFF7F;//1111111101111111把CTR_TX设置为0,清除CTR_RX位

EP1REG=t;

}

//标记发送完成

}

}

/******************************************【端点ERR】******************************************/

else

{

USART_send_str("出错!

端点号是没有开启对端点。

\r\n");

}

}

其他代码:

//设置RXValid.使端点继续接收

voidUSB_enable_ep0_rx(void)

{

u16t=EP0REG;

//USART_send_str("EP0REG=");USART_send_HEX(t>>8);USART_send_HEX(t&0xff);USART_send_str("\r\n");

t&=0x8F8F;//1000111110001111把t位都设置为0

t|=0x8080;//1000000010000000把w0位都设置为1

switch(EP0REG&0x3000)

{

case0x0000:

t|=0x3000;break;

case0x1000:

t|=0x2000;break;

case0x2000:

t|=0x1000;break;

case0x3000:

t|=0x0000;break;

}

EP0REG=t;

//t=EP0REG;

//USART_send_str("EP0REG=");USART_send_HEX(t>>8);USART_send_HEX(t&0xff);USART_send_str("\r\n");

}

//设置RXValid.使端点继续接收

voidUSB_enable_ep1_rx(void)

{

u16t=EP1REG;

t&=0x8F8F;//1000111110001111把t位都设置为0

t|=0x8080;//1000000010000000把w0位都设置为1

switch(EP1REG&0x3000)

{

case0x0000:

t|=0x3000;break;

case0x1000:

t|=0x2000;break;

case0x2000:

t|=0x1000;break;

case0x3000:

t|=0x0000;break;

}

EP1REG=t;

}

//读取端点0收到的数据

u8USB_read_EP0_buf(u8*buf,u32*USB_buf)

{

u16rcv_num;

u8read_cnt;

u8i;

u16temp;

u8j=0;

//接收到的数据

rcv_num=USB_CNT0_RX&0x03FF;

//{

//unsignedchars[32]={0};

//sprintf((char*)s,"端点0读取【%d】字节数据:

",rcv_num);

//USART_send_str(s);

//}

//USART_send_str("\r\n--------------------------------------------------------------------------------\r\n");

//读取次数

read_cnt=(rcv_num+1)>>1;

for(i=0;i

{

temp=*USB_buf++;

buf[j++]=temp&0xFF;

buf[j++]=temp>>8;

}

//for(i=0;i

//{

//USART_send_HEX(buf[i]);

//if((i+1)%16==0)

//{

//USART_send_str("\r\n");

//}

//}

//USART_send_str("\r\n--------------------------------------------------------------------------------\r\n\r\n");

return(j);

}

//读取端点1收到的数据

u8USB_read_EP1_buf(u8*buf,u32*USB_buf)

{

u16rcv_num;

u8read_cnt;

u8i;

u16temp;

u8j=0;

//接收到的数据

rcv_num=USB_CNT1_RX&0x03FF;

{

unsignedchars[32]={0};

sprintf((char*)s,"【端点1】读取【%d】字节数据:

",rcv_num);

USART_send_str(s);

}

USART_send_str("\r\n--------------------------------------------------------------------------------\r\n");

//读取次数

read_cnt=(rcv_num+1)>>1;

for(i=0;i

{

temp=*USB_buf++;

buf[j++]=temp&0xFF;

buf[j++]=temp>>8;

}

for(i=0;i

{

USART_send_HEX(buf[i]);

if((i+1)%16==0)

{

USART_send_str("\r\n");

}

}

USART_send_str("\r\n--------------------------------------------------------------------------------\r\n\r\n");

return(j);

}

//通过端点0发送数据

voidUSB_write_EP0_buf(u8*buf,u32*USB_buf,u8len)

{

u8send_cnt;

u8i;

u8j=0;

u16h,l;

//{

//unsignedchars[32]={0};

//sprintf((char*)s,"端点0发送【%d】字节数据:

",len);

//USART_send_str(s);

//}

//

//USART_send_str("\r\n++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r\n");

//for(i=0;i

//{

//USART_send_HEX(buf[i]);

//if((i+1)%16==0)

//{

//USART_send_str("\r\n");

//}

//}

//USART_send_str("\r\n++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r\n\r\n");

//发送次数

send_cnt=(len+1)>>1;

for(i=0;i

{

l=buf[j++];

h=buf[j++]<<8;

*USB_buf=(h|l);

USB_buf++;

}

//要发送数据的长度

USB_CNT0_TX=len;

//使能发送:

设置VALID

{

u16t=EP0REG;

t&=0x8F8F;//1000111110001111把t位都设置为0

t|=0x8080;//1000000010000000把w0位都设置为1

switch(EP0REG&0x0030)

{

case0x0000:

t|=0x0030;break;

case0x0010:

t|=0x0020;break;

case0x0020:

t|=0x0010;break;

case0x0030:

t|=0x0000;break;

}

EP0REG=t;

}

}

//通过端点1发送数据

voidUSB_write_EP1_buf(u8*buf,u32*USB_buf,u8len)

{

u8send_cnt;

u8i;

u8j=0;

u16h,l;

{

unsignedchars[32]={0};

sprintf((char*)s,"端点1发送【%d】字节数据:

",len);

USART_send_str(s);

}

USART_send_str("\r\n++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r\n");

for(i=0;i

{

USART_send_HEX(buf[i]);

if((i+1)%16==0)

{

USART_send_str("\r\n");

}

}

USART_send_str("\r\n++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r\n\r\n");

//发送次数

send_cnt=(len+1)>>1;

for(i=0;i

{

l=buf[j++];

h=buf[j++]<<8;

*USB_buf=(h|l);

USB_buf++;

}

//要发送数据的长度

USB_CNT1_TX=len;

//使能发送:

设置VALID

{

u16t=EP1REG;

t&=0x8F8F;//1000111110001111把t位都设置为0

t|=0x8080;//1000000010000000把w0位都设置为1

switch(EP1REG&0x0030)

{

case0x0000:

t|=0x0030;break;

case0x0010:

t|=0x0020;break;

case0x0020:

t|=0x0010;break;

case0x0030:

t|=0x0

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 农林牧渔 > 林学

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2