没有合适的资源?快使用搜索试试~ 我知道了~
STM32USB使用方法.doc
1.该资源内容由用户上传,如若侵权请联系客服进行举报
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
版权申诉
0 下载量 109 浏览量
2023-06-06
20:59:44
上传
评论
收藏 83KB DOC 举报
温馨提示
试读
21页
STM32USB使用方法.doc
资源推荐
资源详情
资源评论
STM32-USB 使用方法
开发板买的是奋斗 mini 开发板,芯片是:STM32F103VET6. 如果需要源程序 keil4-arm 工程,上位机 vb。加 qq339396264
要程序。
USB 开发涉及主机和设备,为了避免开发驱动程序,使用 Windows 自带的驱动程序。所以设备枚举成 HID 类设备。USB
鼠标就是标准的 USB-HID 设备。不过操作系统阻止了应用程序直接访问 USB 鼠标返回的报告。所以本例使用自定义 HID
设备。一来免去了开发驱动程序,二来自定义的 HID 设备应用程序和设备可以自由收发数据(仅指数据内容)。
本文主要介绍 STM32 的 USB 模块的简单使用,不会介绍 USB 协议。主要是介绍一下 STM32F103 的 USB 模块使用。
USB 模块从初始化首先是配置和使能时钟
下面是时钟的初始化:
void Set_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 并使能。
然后是配置中断
void USB_Interrupts_Config(void)
{
#define USB_LP_CAN1_RX0_IRQn 20
NVIC_InitTypeDef NVIC_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 断开");
USB_DISCONNECT//这是断开 1.5k 上拉电阻
delay(0x7AFFFF);//延时一会
USB_CONNECT//使能 1.5K 上拉电阻
USART_send_str("USB 连接");
DADDR = 0x0080;//USB 模块使能位。EF 必须置 1
CNTR = 0x0001;//强制复位
CNTR = 0x0000;//退出复位
ISTR = 0x0000;//清除可能产生的假中断
CNTR = (I_CTR | I_RESET);//使能一些中断,为了简单这里只使能了【总线复位中断】和【数据正确传输中断】
ISTR = 0x0000;//清除可能产生的假中断
自此 USB 模块初始化完毕。
以后的流程就在 USB 中断的驱动下执行。
USB 中断函数:
void USB_LP_CAN1_RX0_IRQHandler(void)
{
u16 wIstr;
//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 总线复位中要配置一下寄存器和数据收发的缓冲区。程序如下
void USB_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); //0000 0010 0010 0000 端点 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);//0000 0110 0010 0001 端点 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
//设置 RX Valid .端点 0 可用于接收
{
u16 t = EP0REG;//读出端点 0 寄存器值
t &= 0x8F8F;//1000 1111 1000 1111 由于 t 位写 0 不影响原来的值,写 1 翻转,所以把 t 位都设置为 0
t |= 0x8080;//1000 0000 1000 0000 由于 w0 位写 0 清除,写 1 无影响,所以 w0 位都设置为 1
t |= 0x3000;//0011 0000 0000 0000 把 SRAT_RX[1:0]设置为 1,通过写 1 翻转来实现。
EP0REG = t;
}
}
下面是正确传输中断
//USB 分组正确传输处理
void USB_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
{
u16 t = EP0REG;
t &= 0x8F8F;//1000 1111 1000 1111 把 t 位都设置为 0
t |= 0x8080;//1000 0000 1000 0000 把 w0 位都设置为 1
t &= 0xFF7F;//1111 1111 0111 1111 把 CTR_TX 设置为 0,清除 CTR_RX 位
EP0REG = t;
}
}
if(ISTR & 0x10)//【OUT】分组 or 【SETUP】分组
{
u16 ep0r= EP0REG;
//清除 CTR_RX
{
u16 t = EP0REG;
t &= 0x8F8F;//1000 1111 1000 1111 把 t 位都设置为 0
t |= 0x8080;//1000 0000 1000 0000 把 w0 位都设置为 1
t &= 0x7FFF;//0111 1111 1111 1111 把 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】******************************************/
else if((ISTR & 0x0F) == 1)
{
USART_send_str("端点 1 数据完成传输\r\n");
if(ISTR & 0x10)//【OUT 分组】
{
//清除 CTR_RX
{
u16 t = EP1REG;
t &= 0x8F8F;//1000 1111 1000 1111 把 t 位都设置为 0
t |= 0x8080;//1000 0000 1000 0000 把 w0 位都设置为 1
t &= 0x7FFF;//0111 1111 1111 1111 把 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
{
u16 t = EP1REG;
t &= 0x8F8F;//1000 1111 1000 1111 把 t 位都设置为 0
t |= 0x8080;//1000 0000 1000 0000 把 w0 位都设置为 1
t &= 0xFF7F;//1111 1111 0111 1111 把 CTR_TX 设置为 0,清除 CTR_RX 位
EP1REG = t;
}
//标记发送完成
}
}
/******************************************【端点 ERR】******************************************/
else
{
USART_send_str("出错!端点号是没有开启对端点。\r\n");
}
}
其他代码:
//设置 RX Valid .使端点继续接收
void USB_enable_ep0_rx(void)
{
u16 t = EP0REG;
// USART_send_str("EP0REG = ");USART_send_HEX(t>>8);USART_send_HEX(t&0xff);USART_send_str("\r\n");
t &= 0x8F8F;//1000 1111 1000 1111 把 t 位都设置为 0
t |= 0x8080;//1000 0000 1000 0000 把 w0 位都设置为 1
switch(EP0REG & 0x3000)
{
case 0x0000: t |= 0x3000;break;
case 0x1000: t |= 0x2000;break;
case 0x2000: t |= 0x1000;break;
case 0x3000: 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");
}
//设置 RX Valid .使端点继续接收
void USB_enable_ep1_rx(void)
{
u16 t = EP1REG;
t &= 0x8F8F;//1000 1111 1000 1111 把 t 位都设置为 0
t |= 0x8080;//1000 0000 1000 0000 把 w0 位都设置为 1
switch(EP1REG & 0x3000)
{
case 0x0000: t |= 0x3000;break;
case 0x1000: t |= 0x2000;break;
case 0x2000: t |= 0x1000;break;
case 0x3000: t |= 0x0000;break;
}
EP1REG = t;
}
//读取端点 0 收到的数据
u8 USB_read_EP0_buf(u8 *buf, u32 *USB_buf)
{
剩余20页未读,继续阅读
资源评论
oligaga
- 粉丝: 52
- 资源: 2万+
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功