Stm32 usb to serial port program design analysis
Serial port debugging is becoming increasingly common in projects, and the scarcity of serial port resources has become more evident. Many professionals in this field have a deep understanding of the challenges involved. It's nearly impossible to develop without a USB-to-serial adapter.
Understanding USB virtual serial ports can greatly simplify project development, as it allows for direct power supply and easier debugging. Our company’s future product development will be based on the STM32 platform, evolving from Cortex-M3 to Cortex-M4. Regardless of speed, power consumption, cost, or availability, these microcontrollers are competitive and we prefer not to make unnecessary modifications unless required.
STM32 typically includes a built-in USB serial port. Not using it and adding an external USB-to-serial module would be outdated and inefficient. In terms of the company's needs, the right choice is always better. I used to work with TI, starting from 430, moving to ARM, then to 28XX. ST combines all previous features into one chip. While TI’s ARM may be slower, its DSP performance is comparable to M4, and in some cases even better. Power consumption is impressive, and in certain applications, M4 with floating-point support outperforms fixed-point versions. That’s why TI deliberately reduced the frequency when launching M4 and limited its DSP functions. Every company makes trade-offs, and ST has integrated a CMOS sensor interface. When designing a PCB, it’s important to consider such features.
However, ST’s development routines are somewhat shallow. For example, SuperSpeed USB 2.0 and CMOS interface support are limited, and TCP/IP implementation is not well-documented. The official website is also difficult to navigate, making it hard to find relevant information. Compared to NXP, which offers better support through ZLG, ST still has room for improvement in application-level development. Freescale, on the other hand, excels in network communication applications, and their TCP/IP source code is a pleasure to work with. It seems that while ST is strong in chip design, application development still needs refinement.
In our case, we aim to skip drivers and use low-speed transmission, setting the maximum to 921600 or 100KB/s. It doesn’t matter much; we just need to send simple data. Since our focus is on industrial control, high-speed is not necessary. The main goal is to complete the task efficiently rather than getting bogged down in learning new systems.
If there's no OS support in the routine, we might use Keil’s OS later. Simplicity is key, and uCOS doesn’t support M4’s floating-point operations. For M3, we can move the USB part to uCOS, but for M4, we’ll use KeilOS directly to avoid the hassle of porting an OS.
We start from `main()`:
```c
Set_System(); // System configuration
Set_USBClock(); // USB clock setup
USB_Interrupts_Config(); // USB interrupt configuration
USB_Init(); // USB initialization
while(1) {
if ((count_out != 0) && (bDeviceState == CONFIGURED)) {
USB_To_USART_Send_Data(&buffer_out[0], count_out); // Send data to USART
count_out = 0; // Clear after sending
}
}
```
At first glance, the code looks simple, but it only sends data and doesn't handle receiving. I believe the receiving part is likely handled via interrupts, possibly in the serial port interrupt. We can analyze it later, and maybe it's not needed at all.
Let's go through each function. First, `Set_System()` sets up the system clock. Indeed, it enables the external crystal oscillator, which is 12MHz in this case. Most development boards use 8MHz, so we need to update the `stm32f10x_conf.h` file to reflect the 12MHz frequency.
Next, the code waits for the external crystal to stabilize. If the crystal isn't soldered properly, the system will hang here. If it crashes immediately upon running, check this section.
Then, the code enables the flash prefetch buffer, divides the flash clock by two, and sets the system clock (SYSCLK) to 72MHz. APB2 is set to SYSCLK without division, while APB1 is divided by two. However, timers 2, 3, and 4 still run at 72MHz due to internal multiplication.
The ADC clock is set to 12MHz by dividing the system clock by six. This allows for a conversion time of about 1μs, which is ideal for most applications.
The PLL is configured to multiply the 12MHz input by 6, resulting in 72MHz. Note that for a 12MHz crystal, it can only be multiplied by 6, so care must be taken here.
After enabling the PLL, the code waits for it to stabilize before proceeding. Then, it enables the clocks for GPIOA, GPIOB, and the serial ports, as those are the only resources being used. The USB clock is also enabled somewhere in the process.
Another confusing part is the line: `RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIO_DISCONNECT, ENABLE);`. This enables the USB disconnect pin, which is connected to PE7 according to the schematic. But in the `platform_config.h` file, it's defined as GPIOD, leading to confusion. It's unclear who controls the USB disconnect pin, and there may be a conflict between the schematic and the code.
Next, the code configures the USB disconnect pin as a pull-up, which turns on the transistor and allows the DP+ pin to be pulled up via a 1.5kΩ resistor, facilitating enumeration. However, the specific pin isn't clearly defined in the schematic, raising questions about the actual implementation.
Finally, PA10 is set as a floating input, and PA9 is set as a push-pull output—this matches the standard UART0 configuration used on our boards. With this, the serial port setup is complete.
Uv Curing Hydrogel Film,Glass Protector,Matte Frosted Antiglare Full Cover Screen Protector,Cut Screen Protector Glass
Shenzhen TUOLI Electronic Technology Co., Ltd. , https://www.tlhydrogelprotector.com