STM32F103系列芯片都自带USB,不过STM32F103的USB都只能用来做设备,而不能用作主机。
USBF103自带的USB符合USB2.0规范。
序号 | 文件名 | 作用 | 备注 |
1 | usb_regs.c | 操作USB控制寄存器; | 里面有对各种USB寄存器的底层操作函数; |
2 | usb_init.c | 初始化USB控制器; | 只有一个函数USB_Init,调用其它函数,以使代码规范; |
3 | usb_int.c | 中断处理函数; | 只有两个函数: CTR_LP:负责USB低优先级中断的处理; CTR_HP:负责USB高优先级中断的处理; |
4 | usb_mem.c | 处理PMA数据; | PMA全称为Packet memory area,是stm32内部用于USB/CAN的专用数据缓冲区。 只有两个函数: PMAToUserBufferCopy:将USB数据传送到主机; UserToPMABufferCopy:将主机数据传送到USB; |
5 | usb_core.c | 处理USB2.0协议 | |
6 | usb_sil.c | 为USB端点提供简化的读写访问函数。 | |
序号 | 文件名 | 作用 |
1 | hw_config.c | 配置硬件,比如初始化USB时钟、USB中断、低功耗模式处理等; |
2 | usb_desc.c | 处理Virtual Com描述符; |
3 | usb_endp.c | 处理正确传输中断回调函数,用于非控制传输; |
4 | usb_pwr.c | 管理USB控制器的电源; |
5 | usb_istr.c | 处理USB中断; |
6 | usb_prop.c | 处理所有Virtual Com的相关事件,包括Virtual Com的初始化、复位等操作。 |
序号 | 文件名 | 作用 | 备注 |
1 | stm32_it.c | 处理USB相关中断。 | 包括两个中断服务函数: USB_LP_CAN1_RX0_IRQHandler:调用USB_Istr函数,处理USB发生的各种中断; USBWakeUp_IRQHandler :清除中断标志。 注:为了方便,一般把USB中断相关代码放到hw_config.c里面。 |
int main(void)
{
u16 t;
u16 len;
u16 times=0;
u8 usbstatus=0;
delay_init(); //延时函数初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
uart_init(115200); //串口初始化为115200
USB_Port_Set(0); //USB先断开
delay_ms(700);
USB_Port_Set(1); //USB再次连接
Set_USBClock(); //配置USB时钟,即从72M主频得到48M的USB时钟(1.5分频)
USB_Interrupts_Config(); //设置USB唤醒中断和USB低优先级数据处理中断
USB_Init(); //初始化USB,主要是调用Virtual_Com_Port_init函数,开启USB部分的电源等
while(1)
{
if(usbstatus!=bDeviceState)//USB连接状态发生了改变.
{
usbstatus=bDeviceState;//记录新的状态
if(usbstatus==CONFIGURED)
{
LED1=0;//DS1亮
提示USB连接成功 }else
{
LED1=1;//DS1灭
提示USB断开 }
}
if(USB_USART_RX_STA&0x8000)
{
len=USB_USART_RX_STA&0x3FFF; //得到此次接收到的数据长度
usb_printf("\r\n您发送的消息为:%d\r\n\r\n",len);
for(t=0;t<len;t++)
{
USB_USART_SendData(USB_USART_RX_BUF[t]); //以字节方式,发送给USB
}
usb_printf("\r\n\r\n"); //插入换行
USB_USART_RX_STA=0;
}
else
{
times++;
if(times%5000==0)
{
usb_printf("\r\n战舰STM32开发板USB虚拟串口实验\r\n");
usb_printf("正点原子@ALIENTEK\r\n\r\n");
}
if(times%200==0)
if(times%30==0)
delay_ms(10);
}
}
}
//USB使能连接/断线
//enable:0,断开;
1,允许连接 void USB_Port_Set(u8 enable)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //使能PORTA时钟
if(enable)
{
_SetCNTR(_GetCNTR()&(~(1<<1)));//退出断电模式
}
else
{
_SetCNTR(_GetCNTR()|(1<<1)); // 断电模式
GPIOA->CRH&=0XFFF00FFF;
GPIOA->CRH|=0X00033000;
PAout(12)=0;
}
}
//发送一个字节数据到USB虚拟串口
void USB_USART_SendData(u8 data)
{
uu_txfifo.buffer[uu_txfifo.writeptr]=data;
uu_txfifo.writeptr++;
if(uu_txfifo.writeptr==USB_USART_TXFIFO_SIZE)//超过buf大小了,归零.
{
uu_txfifo.writeptr=0;
}
}
#define USB_USART_TXFIFO_SIZE 1024 //USB虚拟串口发送FIFO大小
//定义一个USB USART FIFO结构体
typedef struct
{
u8 buffer[USB_USART_TXFIFO_SIZE]; //buffer
vu16 writeptr; //写指针
vu16 readptr; //读指针
}_usb_usart_fifo;
extern _usb_usart_fifo uu_txfifo; //USB串口发送FIFO
//Function Name : EP1_IN_Callback
void EP1_IN_Callback (void)
{
u16 USB_Tx_ptr;
u16 USB_Tx_length;
if(uu_txfifo.readptr==uu_txfifo.writeptr)//无任何数据要发送,直接退出
{
return;
}
if(uu_txfifo.readptr<uu_txfifo.writeptr) //没有超过数组, 读指针 < 写指针
{
USB_Tx_length=uu_txfifo.writeptr-uu_txfifo.readptr; //得到要发送的数据长度
}
{
USB_Tx_length=USB_USART_TXFIFO_SIZE-uu_txfifo.readptr; //得到要发送的数据长度
}
{
USB_Tx_length=VIRTUAL_COM_PORT_DATA_SIZE; //此次发送数据量
}
USB_Tx_ptr = uu_txfifo.readptr; //发送起始地址
uu_txfifo.readptr += USB_Tx_length; //读指针偏移
if(uu_txfifo.readptr>=USB_USART_TXFIFO_SIZE) //读指针归零
{
uu_txfifo.readptr=0;
}
UserToPMABufferCopy(&uu_txfifo.buffer[USB_Tx_ptr], ENDP1_TXADDR, USB_Tx_length);
SetEPTxCount(ENDP1, USB_Tx_length);
SetEPTxValid(ENDP1);
}
//Function Name : EP3_OUT_Callback
void EP3_OUT_Callback(void)
{
u16 USB_Rx_Cnt;
USB_Rx_Cnt = USB_SIL_Read(EP3_OUT, USB_Rx_Buffer); //得到USB接收到的数据及其长度
USB_To_USART_Send_Data(USB_Rx_Buffer, USB_Rx_Cnt); //处理数据(其实就是保存数据)
SetEPRxValid(ENDP3); //使能端点3的数据接收
}
u8 USB_USART_RX_BUF[USB_USART_REC_LEN];
//接收缓冲,最大 USART_REC_LEN 个字节.u16 USB_USART_RX_STA=0; //
接收状态
,bit15, 接收完成标志,
bit14, 接收到 0x0d,
bit13~0, 接收到的有效字节数目//处理从USB虚拟串口接收到的数据,
databuffer:数据缓存区,Nb_bytes:接收到的字节数.void USB_To_USART_Send_Data(u8* data_buffer, u8 Nb_bytes)
{
u8 i;
u8 res;
for(i=0;i<Nb_bytes;i++)
{
res=data_buffer[i];
if((USB_USART_RX_STA&0x8000) == 0) //接收未完成
{
if(USB_USART_RX_STA & 0x4000) //接收到了0x0d
{
if(res != 0x0a)
USB_USART_RX_STA = 0; //接收错误,重新开始
else
USB_USART_RX_STA |= 0x8000; //接收完成了
}
else //还没收到0X0d
{
if(res == 0x0d)
USB_USART_RX_STA |= 0x4000;
else
{
USB_USART_RX_BUF[USB_USART_RX_STA&0X3FFF] = res;
USB_USART_RX_STA++;
if(USB_USART_RX_STA > (USB_USART_REC_LEN-1))
USB_USART_RX_STA = 0; //接收数据错误,重新开始接收
}
}
}
}
}