The entire driver consists of four files:
uart.h
uart.c
COMMRTOS.H
COMMRTOS.c
The first two files are encapsulations of the basic functions of the serial port.
The code of uart.h is as follows:
- #ifndef _UART_H_
- #define _UART_H_
- void USART1_Init(void);
- void USART2_Init(void);
- void UART_PutChar(USART_TypeDef* USARTx, uint8_t Data);
- void UART_PutStr (USART_TypeDef* USARTx, uint8_t *str);
- uint8_t UART_GetChar(USART_TypeDef* USARTx);
- #endif
uart.c code
- #include "stm32f10x.h"
- void USART1_Init(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- USART_InitTypeDef USART_InitStructure;
- NVIC_InitTypeDef NVIC_InitStructure;
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE);
- /* Configure USART Tx as alternate function push-pull */
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOA, &GPIO_InitStructure);
- /* Configure USART Rx as input floating */
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
- GPIO_Init(GPIOA, &GPIO_InitStructure);
- USART_InitStructure.USART_BaudRate = 9600;
- USART_InitStructure.USART_WordLength = USART_WordLength_8b;
- USART_InitStructure.USART_StopBits = USART_StopBits_1;
- USART_InitStructure.USART_Parity = USART_Parity_No;
- USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
- USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
- USART_Init(USART1, &USART_InitStructure);
- USART_Cmd(USART1, ENABLE);
- NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
- NVIC_Init(&NVIC_InitStructure);
- }
- void USART2_Init(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- USART_InitTypeDef USART_InitStructure;
- NVIC_InitTypeDef NVIC_InitStructure;
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD | RCC_APB2Periph_AFIO, ENABLE);
- /* Configure USART Tx as alternate function push-pull */
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOD, &GPIO_InitStructure);
- /* Configure USART Rx as input floating */
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
- GPIO_Init(GPIOD, &GPIO_InitStructure);
- GPIO_PinRemapConfig(GPIO_Remap_USART2, ENABLE);
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
- USART_InitStructure.USART_BaudRate = 9600;
- USART_InitStructure.USART_WordLength = USART_WordLength_8b;
- USART_InitStructure.USART_StopBits = USART_StopBits_1;
- USART_InitStructure.USART_Parity = USART_Parity_No;
- USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
- USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
- USART_Init(USART2, &USART_InitStructure);
- USART_Cmd(USART2, ENABLE);
- NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
- NVIC_Init(&NVIC_InitStructure);
- }
- void UART_PutChar(USART_TypeDef* USARTx, uint8_t Data)
- {
- //while (USART_GetFlagStatus(USARTx, USART_FLAG_TC) == RESET ) {};
- while((USARTx->SR & USART_FLAG_TXE) == 0x00) {};
- //USART_SendData (USARTx, Data);
- USARTx->DR = Data;
- }
- void UART_PutStr(USART_TypeDef* USARTx, uint8_t *str)
- {
- while(0 != *str)
- {
- UART_PutChar(USARTx, *str);
- str++;
- }
- }
- uint8_t UART_GetChar(USART_TypeDef* USARTx)
- {
- //while( USART_GetFlagStatus(USARTx, USART_FLAG_RXNE) == RESET) {};
- while((USARTx->SR & USART_FLAG_RXNE) == 0x00) {};
- //return USART_ReceiveData(USARTx);
- return (USARTx->DR & 0xff);
- }
The code of commrtos.h is as follows:
- #ifndef _COMMRTOS_H_
- #define _COMMRTOS_H_
- #ifndef CFG_H
- #define COMM_RX_BUF_SIZE 64 /* Number of characters in Rx ring buffer */
- #define COMM_TX_BUF_SIZE 64 /* Number of characters in Tx ring buffer */
- #endif
- /*
- *************************************************** *************************************************** *****
- *CONSTANTS
- *************************************************** *************************************************** *****
- */
- #ifndef FALSE
- #define FALSE 0x00
- #endif
- #ifndef TRUE
- #define TRUE 0xff
- #endif
- #ifndef NUL
- #define NUL 0x00
- #endif
- #defineCOM1 0
- #defineCOM2 1
- /* ERROR CODES */
- #define COMM_NO_ERR 0 /* Function call was successful */
- #define COMM_BAD_CH 1 /* Invalid communications port channel */
- #define COMM_RX_EMPTY 2 /* Rx buffer is empty, no character available */
- #define COMM_TX_FULL 3 /* Tx buffer is full, could not deposit character */
- #define COMM_TX_EMPTY 4 /* If the Tx buffer is empty. */
- #define COMM_RX_TIMEOUT 5 /* If a timeout occurred while waiting for a character*/
- #define COMM_TX_TIMEOUT 6 /* If a timeout occurred while waiting to send a char.*/
- #define COMM_PARITY_NONE 0 /* Defines for setting parity */
- #define COMM_PARITY_ODD 1
- #define COMM_PARITY_EVEN 2
- unsigned char CommGetChar(unsigned char ch, unsigned short to, unsigned char *err);
- void COMInit(void);
- unsigned char CommIsEmpty(unsigned char ch);
- unsigned char CommIsFull(unsigned char ch);
- unsigned char CommPutChar(unsigned char ch, unsigned char c, unsigned short to);
- void CommPutStr(unsigned char ch, uint8_t *str);
- #endif
The code of commrtos.c is as follows:
- #include "stm32f10x_usart.h"
- #include "includes.h"
- #include "COMMRTOS.H"
- /*
- * DATA TYPES
- */
- typedef struct {
- unsigned short RingBufRxCtr; /* Number of characters in the Rx ring buffer */
- OS_EVENT *RingBufRxSem; /* Pointer to Rx semaphore */
- unsigned char *RingBufRxInPtr; /* Pointer to where next character will be inserted */
- unsigned char *RingBufRxOutPtr; /* Pointer from where next character will be extracted */
- unsigned char RingBufRx[COMM_RX_BUF_SIZE]; /* Ring buffer character storage (Rx) */
- unsigned short RingBufTxCtr; /* Number of characters in the Tx ring buffer */
- OS_EVENT *RingBufTxSem; /* Pointer to Tx semaphore */
- unsigned char *RingBufTxInPtr; /* Pointer to where next character will be inserted */
- unsigned char *RingBufTxOutPtr; /* Pointer from where next character will be extracted */
- unsigned char RingBufTx[COMM_TX_BUF_SIZE]; /* Ring buffer character storage (Tx) */
- } COMM_RING_BUF;
- /*
- * GLOBAL VARIABLES
- */
- COMM_RING_BUF Comm1Buf;
- COMM_RING_BUF Comm2Buf;
- static void COMEnableTxInt(unsigned char port)
- {
- static USART_TypeDef* map[2] = {USART1, USART2};
- //USART_ITConfig(map[port], USART_IT_TXE, ENABLE);
- map[port]->CR1 |= USART_FLAG_TXE;
- }
- /*
- *************************************************** *************************************************** *****
- * REMOVE CHARACTER FROM RING BUFFER
- *
- *
- * Description: This function is called by your application to obtain a character from the communications
- * channel. The function will wait for a character to be received on the serial channel or
- * until the function times out.
- * Arguments: 'ch' is the COMM port channel number and can either be:
- *COMM1
- *COMM2
- * 'to' is the amount of time (in clock ticks) that the calling function is willing to
- * wait for a character to arrive. If you specify a timeout of 0, the function will
- * wait forever for a character to arrive.
- * 'err' is a pointer to where an error code will be placed:
- * *err is set to COMM_NO_ERR if a character has been received
- * *err is set to COMM_RX_TIMEOUT if a timeout occurred
- * *err is set to COMM_BAD_CH if you specify an invalid channel number
- * Returns: The character in the buffer (or NUL if a timeout occurred)
- *************************************************** *************************************************** *****
- */
- unsigned char CommGetChar(unsigned char ch, unsigned short to, unsigned char *err)
- {
- unsigned char c;
- unsigned char oserr;
- COMM_RING_BUF *pbuf;
- OS_CPU_SR cpu_sr;
- switch(ch)
- { /* Obtain pointer to communications channel */
- case COM1:
- pbuf = &Comm1Buf;
- break;
- case COM2:
- pbuf = &Comm2Buf;
- break;
- default:
- *err = COMM_BAD_CH;
- return (NUL);
- }
- OSSemPend(pbuf->RingBufRxSem, to, &oserr); /* Wait for character to arrive */
- if (oserr == OS_TIMEOUT)
- { /* See if characters received within timeout*/
- *err = COMM_RX_TIMEOUT; /* No, return error code */
- return (NUL);
- }
- else
- {
- OS_ENTER_CRITICAL();
- pbuf->RingBufRxCtr--; /* Yes, decrement character count */
- c = *pbuf->RingBufRxOutPtr++; /* Get character from buffer */
- if(pbuf->RingBufRxOutPtr == &pbuf->RingBufRx[COMM_RX_BUF_SIZE])
- { /* Wrap OUT pointer */
- pbuf->RingBufRxOutPtr = &pbuf->RingBufRx[0];
- }
- OS_EXIT_CRITICAL();
- *err = COMM_NO_ERR;
- return (c);
- }
- }
- void CommPutStr(unsigned char ch, uint8_t *str)
- {
- while(0 != *str)
- {
- CommPutChar(ch, *str, 0);
- str++;
- }
- }
- static unsigned char COMGetTxChar(unsigned char ch, unsigned char *err)
- {
- unsigned char c;
- COMM_RING_BUF *pbuf;
- switch(ch)
- { /* Obtain pointer to communications channel */
- case COM1:
- pbuf = &Comm1Buf;
- break;
- case COM2:
- pbuf = &Comm2Buf;
- break;
- default:
- *err = COMM_BAD_CH;
- return (NUL);
- }
- if(pbuf->RingBufTxCtr > 0)
- { /* See if buffer is empty */
- pbuf->RingBufTxCtr--; /* No, decrement character count */
- c = *pbuf->RingBufTxOutPtr++; /* Get character from buffer */
- if(pbuf->RingBufTxOutPtr == &pbuf->RingBufTx[COMM_TX_BUF_SIZE])
- { /* Wrap OUT pointer */
- pbuf->RingBufTxOutPtr = &pbuf->RingBufTx[0];
- }
- OSSemPost(pbuf->RingBufTxSem); /* Indicate that character will be sent */
- *err = COMM_NO_ERR;
- return (c); /* Characters are still available */
- }
- else
- {
- *err = COMM_TX_EMPTY;
- return (NUL); /* Buffer is empty */
- }
- }
- /*
- *************************************************** *************************************************** *****
- * INITIALIZE COMMUNICATIONS MODULE
- * Description: This function is called by your application to initialize the communications module. You
- * must call this function before calling any other functions.
- * Arguments : none
- *************************************************** *************************************************** *****
- */
- void COMInit(void)
- {
- COMM_RING_BUF *pbuf;
- pbuf = &Comm1Buf; /* Initialize the ring buffer for COMM1 */
- pbuf->RingBufRxCtr = 0;
- pbuf->RingBufRxInPtr = &pbuf->RingBufRx[0];
- pbuf->RingBufRxOutPtr = &pbuf->RingBufRx[0];
- pbuf->RingBufRxSem = OSSemCreate(0);
- pbuf->RingBufTxCtr = 0;
- pbuf->RingBufTxInPtr = &pbuf->RingBufTx[0];
- pbuf->RingBufTxOutPtr = &pbuf->RingBufTx[0];
- pbuf->RingBufTxSem = OSSemCreate(COMM_TX_BUF_SIZE);
- pbuf = &Comm2Buf; /* Initialize the ring buffer for COMM2 */
- pbuf->RingBufRxCtr = 0;
- pbuf->RingBufRxInPtr = &pbuf->RingBufRx[0];
- pbuf->RingBufRxOutPtr = &pbuf->RingBufRx[0];
- pbuf->RingBufRxSem = OSSemCreate(0);
- pbuf->RingBufTxCtr = 0;
- pbuf->RingBufTxInPtr = &pbuf->RingBufTx[0];
- pbuf->RingBufTxOutPtr = &pbuf->RingBufTx[0];
- pbuf->RingBufTxSem = OSSemCreate(COMM_TX_BUF_SIZE);
- }
- /*
- *************************************************** *************************************************** *****
- * SEE IF RX CHARACTER BUFFER IS EMPTY
- *
- *
- * Description: This function is called by your application to see if any character is available from the
- * communications channel. If at least one character is available, the function returns
- * FALSE otherwise, the function returns TRUE.
- * Arguments: 'ch' is the COMM port channel number and can either be:
- *COMM1
- *COMM2
- * Returns: TRUE if the buffer IS empty.
- * FALSE if the buffer IS NOT empty or you have specified an incorrect channel.
- *************************************************** *************************************************** *****
- */
- unsigned char CommIsEmpty(unsigned char ch)
- {
- unsigned char empty;
- COMM_RING_BUF *pbuf;
- OS_CPU_SR cpu_sr;
- switch(ch)
- { /* Obtain pointer to communications channel */
- case COM1:
- pbuf = &Comm1Buf;
- break;
- case COM2:
- pbuf = &Comm2Buf;
- break;
- default:
- return (TRUE);
- }
- OS_ENTER_CRITICAL();
- if(pbuf->RingBufRxCtr > 0)
- { /* See if buffer is empty */
- empty = FALSE; /* Buffer is NOT empty */
- }
- else
- {
- empty = TRUE; /* Buffer is empty */
- }
- OS_EXIT_CRITICAL();
- return (empty);
- }
- /*
- *************************************************** *************************************************** *****
- * SEE IF TX CHARACTER BUFFER IS FULL
- * Description: This function is called by your application to see if any more characters can be placed
- * in the Tx buffer. In other words, this function check to see if the Tx buffer is full.
- * If the buffer is full, the function returns TRUE otherwise, the function returns FALSE.
- * Arguments: 'ch' is the COMM port channel number and can either be:
- *COMM1
- *COMM2
- * Returns: TRUE if the buffer IS full.
- * FALSE if the buffer IS NOT full or you have specified an incorrect channel.
- *************************************************** *************************************************** *****
- */
- unsigned char CommIsFull(unsigned char ch)
- {
- unsigned char full;
- COMM_RING_BUF *pbuf;
- OS_CPU_SR cpu_sr;
- switch(ch)
- { /* Obtain pointer to communications channel */
- case COM1:
- pbuf = &Comm1Buf;
- break;
- case COM2:
- pbuf = &Comm2Buf;
- break;
- default:
- return (TRUE);
- }
- OS_ENTER_CRITICAL();
- if(pbuf->RingBufTxCtr < COMM_TX_BUF_SIZE)
- { /* See if buffer is full */
- full = FALSE; /* Buffer is NOT full */
- }
- else
- {
- full = TRUE; /* Buffer is full */
- }
- OS_EXIT_CRITICAL();
- return (full);
- }
- /*
- *************************************************** *************************************************** *****
- * OUTPUT CHARACTER
- *
- *
- * Description: This function is called by your application to send a character on the communications
- * channel. The function will wait for the buffer to empty out if the buffer is full.
- * The function returns to your application if the buffer doesn't empty within the specified
- * timeout. A timeout value of 0 means that the calling function will wait forever for the
- * buffer to empty out. The character to send is first inserted into the Tx buffer and will
- * be sent by the Tx ISR. If this is the first character placed into the buffer, the Tx ISR
- * will be enabled.
- * Arguments: 'ch' is the COMM port channel number and can either be:
- *COMM1
- *COMM2
- * 'c' is the character to send.
- * 'to' is the timeout (in clock ticks) to wait in case the buffer is full. If you
- * specify a timeout of 0, the function will wait forever for the buffer to empty.
- * Returns: COMM_NO_ERR if the character was placed in the Tx buffer
- * COMM_TX_TIMEOUT if the buffer didn't empty within the specified timeout period
- * COMM_BAD_CH if you specify an invalid channel number
- *************************************************** *************************************************** *****
- */
- unsigned char CommPutChar(unsigned char ch, unsigned char c, unsigned short to)
- {
- unsigned char oserr;
- COMM_RING_BUF *pbuf;
- OS_CPU_SR cpu_sr;
- switch(ch)
- { /* Obtain pointer to communications channel */
- case COM1:
- pbuf = &Comm1Buf;
- break;
- case COM2:
- pbuf = &Comm2Buf;
- break;
- default:
- return (COMM_BAD_CH);
- }
- OSSemPend(pbuf->RingBufTxSem, to, &oserr); /* Wait for space in Tx buffer */
- if (oserr == OS_TIMEOUT)
- {
- return (COMM_TX_TIMEOUT); /* Timed out, return error code */
- }
- OS_ENTER_CRITICAL();
- pbuf->RingBufTxCtr++; /* No, increment character count */
- *pbuf->RingBufTxInPtr++ = c; /* Put character into buffer */
- if(pbuf->RingBufTxInPtr == &pbuf->RingBufTx[COMM_TX_BUF_SIZE])
- { /* Wrap IN pointer */
- pbuf->RingBufTxInPtr = &pbuf->RingBufTx[0];
- }
- if(pbuf->RingBufTxCtr == 1)
- { /* See if this is the first character */
- COMEnableTxInt(ch); /* Yes, Enable Tx interrupts */
- }
- OS_EXIT_CRITICAL();
- return (COMM_NO_ERR);
- }
- /*
- *************************************************** *************************************************** *****
- * INSERT CHARACTER INTO RING BUFFER
- *
- *
- * Description: This function is called by the Rx ISR to insert a character into the receive ring buffer.
- * Arguments: 'ch' is the COMM port channel number and can either be:
- *COMM1
- *COMM2
- * 'c' is the character to insert into the ring buffer. If the buffer is full, the
- * character will not be inserted, it will be lost.
- *************************************************** *************************************************** *****
- */
- static void COMPutRxChar(unsigned char ch, unsigned char c)
- {
- COMM_RING_BUF *pbuf;
- switch(ch)
- { /* Obtain pointer to communications channel */
- case COM1:
- pbuf = &Comm1Buf;
- break;
- case COM2:
- pbuf = &Comm2Buf;
- break;
- default:
- return;
- }
- if(pbuf->RingBufRxCtr < COMM_RX_BUF_SIZE)
- { /* See if buffer is full */
- pbuf->RingBufRxCtr++; /* No, increment character count */
- *pbuf->RingBufRxInPtr++ = c; /* Put character into buffer */
- if(pbuf->RingBufRxInPtr == &pbuf->RingBufRx[COMM_RX_BUF_SIZE])
- { /* Wrap IN pointer */
- pbuf->RingBufRxInPtr = &pbuf->RingBufRx[0];
- }
- OSSemPost(pbuf->RingBufRxSem); /* Indicate that character was received */
- }
- }
- // This function is called by the Rx ISR to insert a character into the receive ring buffer.
- void USART1_IRQHandler(void)
- {
- unsigned int data;
- unsigned char err;
- OS_CPU_SR cpu_sr;
- OS_ENTER_CRITICAL(); /* Tell uC/OS-II that we are starting an ISR */
- OSIntNesting++;
- OS_EXIT_CRITICAL();
- if(USART1->SR & 0x0F)
- {
- // See if we have some kind of error
- // Clear interrupt (do nothing about it!)
- data = USART1->DR;
- }
- else if(USART1->SR & USART_FLAG_RXNE) //Receive Data Reg Full Flag
- {
- data = USART1->DR;
- COMPutRxChar(COM1, data); // Insert received character into buffer
- }
- else if(USART1->SR & USART_FLAG_TXE)
- {
- data = COMGetTxChar(COM1, &err); // Get next character to send.
- if (err == COMM_TX_EMPTY)
- { // Do we have anymore characters to send?
- // No, Disable Tx interrupts
- //USART_ITConfig(USART1, USART_IT_TXE| USART_IT_TC, DISABLE);
- USART1->CR1 &= ~USART_FLAG_TXE | USART_FLAG_TC;
- }
- else
- {
- USART1->DR = data; // Yes, Send character
- }
- }
- OSIntExit();
- }
- void USART2_IRQHandler(void)
- {
- unsigned int data;
- unsigned char err;
- OS_CPU_SR cpu_sr;
- OS_ENTER_CRITICAL(); /* Tell uC/OS-II that we are starting an ISR */
- OSIntNesting++;
- OS_EXIT_CRITICAL();
- if(USART2->SR & 0x0F)
- {
- // See if we have some kind of error
- // Clear interrupt (do nothing about it!)
- data = USART2->DR;
- }
- else if(USART2->SR & USART_FLAG_RXNE) //Receive Data Reg Full Flag
- {
- data = USART2->DR;
- COMPutRxChar(COM2, data); // Insert received character into buffer
- }
- else if(USART2->SR & USART_FLAG_TXE)
- {
- data = COMGetTxChar(COM2, &err); // Get next character to send.
- if (err == COMM_TX_EMPTY)
- { // Do we have anymore characters to send?
- // No, Disable Tx interrupts
- //USART_ITConfig(USART2, USART_IT_TXE| USART_IT_TC, DISABLE);
- USART2->CR1 &= ~USART_FLAG_TXE | USART_FLAG_TC;
- }
- else
- {
- USART2->DR = data; // Yes, Send character
- }
- }
- OSIntExit();
- }
Here is another test code:
- #include "stm32f10x.h"
- #include "uart.h"
- #include "led.h"
- #include "COMMRTOS.H"
- #include "ucos_ii.h"
- #define TASK_STK_SIZE 128
- OS_STK TaskStartStk[TASK_STK_SIZE];
- OS_STK TaskUartReadStk[TASK_STK_SIZE];
- void TaskUartRead(void *pdata)
- {
- unsigned char err;
- unsigned char c;
- for(;;)
- {
- c = CommGetChar(COM2, 0, &err);
- if (err == COMM_NO_ERR)
- CommPutChar(COM2, c, 0);
- }
- }
- void TaskStart(void *pdata)
- {
- SysTick_Config(SystemCoreClock/10);
- USART1_Init();
- USART2_Init();
- COMInit();
- //USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
- //USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
- USART1->CR1 |= USART_FLAG_RXNE;
- USART2->CR1 |= USART_FLAG_RXNE;
- OSTaskCreate(TaskUartRead, (void *)0, &(TaskUartReadStk[TASK_STK_SIZE-1]), 2);
- UART_PutStr (USART2, "USART2 Hello World!\n\r");
- //CommPutChar(COM2, '+', 0);
- CommPutStr(COM2, "CommPutCharB\n\r");
- for(;;)
- {
- LED_Spark();
- CommPutChar(COM2, '+', 0);
- OSTimeDly(10);
- }
- }
- int main(void)
- {
- SystemInit();
- LED_Init();
- OSInit();
- OSTaskCreate(TaskStart, (void *)0, &(TaskStartStk[TASK_STK_SIZE-1]), 1);
- OSStart();
- for(;;)
- {
- }
- }
Previous article:STM32F10x Study Notes 8 (USART implements serial communication DMA method)
Next article:STM32F10x Study Notes 7 (Independent Watchdog IWDG Module)
- Popular Resources
- Popular amplifiers
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- LED chemical incompatibility test to see which chemicals LEDs can be used with
- Application of ARM9 hardware coprocessor on WinCE embedded motherboard
- What are the key points for selecting rotor flowmeter?
- LM317 high power charger circuit
- A brief analysis of Embest's application and development of embedded medical devices
- Single-phase RC protection circuit
- stm32 PVD programmable voltage monitor
- Introduction and measurement of edge trigger and level trigger of 51 single chip microcomputer
- Improved design of Linux system software shell protection technology
- What to do if the ABB robot protection device stops
- Huawei's Strategic Department Director Gai Gang: The cumulative installed base of open source Euler operating system exceeds 10 million sets
- Download from the Internet--ARM Getting Started Notes
- Learn ARM development(22)
- Learn ARM development(21)
- Learn ARM development(20)
- Learn ARM development(19)
- Learn ARM development(14)
- Learn ARM development(15)
- Analysis of the application of several common contact parts in high-voltage connectors of new energy vehicles
- Wiring harness durability test and contact voltage drop test method
- Evaluation summary: Free application for CB5654 intelligent voice development board (Xuantie 803)
- 8 Way Splitter Workspace_____Genesys2020__1/8
- TI C64X+ General Library Function User Manual
- bluenrg chat example
- [AB32VG1 development board review] Serial dot matrix module display driver
- Milliohm meter based on [EVAL-ADICUP360] - Summary
- Review summary: Infineon's revolutionary photoacoustic spectroscopy (PAS) CO2 sensor
- UART interface algorithm transplantation encryption chip debugging skills - algorithm debugging
- Get the first experience! Raspberry Pi's first MCU product - Raspberry Pi Pico free review is here~
- What requirements does an industrial-grade 4G router need to meet?