STM32F10x study notes 7 (USART realizes serial communication 3)

Publisher:RadiantSmileLatest update time:2016-05-05 Source: eefocusKeywords:STM32F10x  USART Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere
In the previous study note "STM32F10x Study Note 6 (USART Serial Communication 2)", a serial port driver using a ring buffer was given. Recently, I studied the porting of uCOS-II on STM32. Here is another serial port driver using the semaphore of uCOS-II. The basic framework of the entire driver is no different from the previous one, so I won't introduce it in detail. I will just paste the code:

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:

 
  1. #ifndef _UART_H_  
  2. #define _UART_H_  
  3.   
  4. void USART1_Init(void);  
  5. void USART2_Init(void);  
  6. void UART_PutChar(USART_TypeDef* USARTx, uint8_t Data);  
  7. void UART_PutStr (USART_TypeDef* USARTx, uint8_t *str);  
  8. uint8_t UART_GetChar(USART_TypeDef* USARTx);  
  9.   
  10. #endif  

uart.c code

 

 
  1. #include "stm32f10x.h"  
  2.   
  3. void USART1_Init(void)  
  4. {  
  5.     GPIO_InitTypeDef GPIO_InitStructure;  
  6.     USART_InitTypeDef USART_InitStructure;  
  7.     NVIC_InitTypeDef NVIC_InitStructure;  
  8.   
  9.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE);  
  10.   
  11.     /* Configure USART Tx as alternate function push-pull */  
  12.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  
  13.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;  
  14.     GPIO_InitStructure.GPIO_Speed ​​= GPIO_Speed_50MHz;  
  15.     GPIO_Init(GPIOA, &GPIO_InitStructure);  
  16.   
  17.     /* Configure USART Rx as input floating */  
  18.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;  
  19.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;  
  20.     GPIO_Init(GPIOA, &GPIO_InitStructure);  
  21.   
  22.     USART_InitStructure.USART_BaudRate = 9600;  
  23.     USART_InitStructure.USART_WordLength = USART_WordLength_8b;  
  24.     USART_InitStructure.USART_StopBits = USART_StopBits_1;  
  25.     USART_InitStructure.USART_Parity = USART_Parity_No;  
  26.     USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;  
  27.     USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;  
  28.     USART_Init(USART1, &USART_InitStructure);  
  29.   
  30.     USART_Cmd(USART1, ENABLE);  
  31.   
  32.     NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;  
  33.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  
  34.     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  
  35.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  
  36.     NVIC_Init(&NVIC_InitStructure);  
  37. }  
  38.   
  39. void USART2_Init(void)  
  40. {  
  41.     GPIO_InitTypeDef GPIO_InitStructure;  
  42.     USART_InitTypeDef USART_InitStructure;  
  43.     NVIC_InitTypeDef NVIC_InitStructure;  
  44.   
  45.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD | RCC_APB2Periph_AFIO, ENABLE);  
  46.   
  47.     /* Configure USART Tx as alternate function push-pull */  
  48.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  
  49.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;  
  50.     GPIO_InitStructure.GPIO_Speed ​​= GPIO_Speed_50MHz;  
  51.     GPIO_Init(GPIOD, &GPIO_InitStructure);  
  52.   
  53.     /* Configure USART Rx as input floating */  
  54.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;  
  55.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;  
  56.     GPIO_Init(GPIOD, &GPIO_InitStructure);  
  57.   
  58.     GPIO_PinRemapConfig(GPIO_Remap_USART2, ENABLE);  
  59.     RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);  
  60.   
  61.     USART_InitStructure.USART_BaudRate = 9600;  
  62.     USART_InitStructure.USART_WordLength = USART_WordLength_8b;  
  63.     USART_InitStructure.USART_StopBits = USART_StopBits_1;  
  64.     USART_InitStructure.USART_Parity = USART_Parity_No;  
  65.     USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;  
  66.     USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;  
  67.     USART_Init(USART2, &USART_InitStructure);  
  68.   
  69.     USART_Cmd(USART2, ENABLE);  
  70.   
  71.     NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;  
  72.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;  
  73.     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;  
  74.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  
  75.     NVIC_Init(&NVIC_InitStructure);  
  76. }  
  77.   
  78. void UART_PutChar(USART_TypeDef* USARTx, uint8_t Data)  
  79. {  
  80.     //while (USART_GetFlagStatus(USARTx, USART_FLAG_TC) == RESET ) {};  
  81.     while((USARTx->SR & USART_FLAG_TXE) == 0x00) {};  
  82.     //USART_SendData (USARTx, Data);  
  83.     USARTx->DR = Data;  
  84. }  
  85. void UART_PutStr(USART_TypeDef* USARTx, uint8_t *str)  
  86. {  
  87.     while(0 != *str)  
  88.     {  
  89.         UART_PutChar(USARTx, *str);  
  90.         str++;  
  91.     }  
  92. }  
  93.   
  94. uint8_t UART_GetChar(USART_TypeDef* USARTx)  
  95. {  
  96.     //while( USART_GetFlagStatus(USARTx, USART_FLAG_RXNE) == RESET) {};  
  97.     while((USARTx->SR & USART_FLAG_RXNE) == 0x00) {};  
  98.     //return USART_ReceiveData(USARTx);  
  99.     return (USARTx->DR & 0xff);  
  100. }  

The code of commrtos.h is as follows:

 

 
  1. #ifndef _COMMRTOS_H_  
  2. #define _COMMRTOS_H_  
  3.   
  4. #ifndef CFG_H  
  5.   
  6. #define COMM_RX_BUF_SIZE 64 /* Number of characters in Rx ring buffer */  
  7. #define COMM_TX_BUF_SIZE 64 /* Number of characters in Tx ring buffer */  
  8.   
  9. #endif  
  10.   
  11. /* 
  12. *************************************************** *************************************************** ***** 
  13. *CONSTANTS 
  14. *************************************************** *************************************************** ***** 
  15. */  
  16. #ifndef FALSE  
  17. #define FALSE 0x00  
  18. #endif  
  19.   
  20. #ifndef TRUE  
  21. #define TRUE 0xff  
  22. #endif  
  23.   
  24. #ifndef NUL  
  25. #define NUL 0x00  
  26. #endif  
  27.   
  28. #defineCOM1 0  
  29. #defineCOM2 1  
  30.   
  31. /* ERROR CODES */  
  32. #define COMM_NO_ERR 0 /* Function call was successful */  
  33. #define COMM_BAD_CH 1 /* Invalid communications port channel */  
  34. #define COMM_RX_EMPTY 2 /* Rx buffer is empty, no character available */  
  35. #define COMM_TX_FULL 3 /* Tx buffer is full, could not deposit character */  
  36. #define COMM_TX_EMPTY 4 /* If the Tx buffer is empty. */  
  37. #define COMM_RX_TIMEOUT 5 /* If a timeout occurred while waiting for a character*/  
  38. #define COMM_TX_TIMEOUT 6 /* If a timeout occurred while waiting to send a char.*/  
  39.   
  40.   
  41. #define COMM_PARITY_NONE 0 /* Defines for setting parity */  
  42. #define COMM_PARITY_ODD 1  
  43. #define COMM_PARITY_EVEN 2  
  44.   
  45. unsigned char CommGetChar(unsigned char ch, unsigned short to, unsigned char *err);  
  46. void COMInit(void);  
  47. unsigned char CommIsEmpty(unsigned char ch);  
  48. unsigned char CommIsFull(unsigned char ch);  
  49. unsigned char CommPutChar(unsigned char ch, unsigned char c, unsigned short to);  
  50. void CommPutStr(unsigned char ch, uint8_t *str);  
  51.   
  52. #endif  

 

The code of commrtos.c is as follows:
 

 
  1. #include "stm32f10x_usart.h"  
  2. #include "includes.h"  
  3. #include "COMMRTOS.H"  
  4.   
  5. /* 
  6.  * DATA TYPES 
  7.  */  
  8. typedef struct {  
  9.     unsigned short RingBufRxCtr; /* Number of characters in the Rx ring buffer */  
  10.     OS_EVENT *RingBufRxSem; /* Pointer to Rx semaphore */  
  11.     unsigned char *RingBufRxInPtr; /* Pointer to where next character will be inserted */  
  12.     unsigned char *RingBufRxOutPtr; /* Pointer from where next character will be extracted */  
  13.     unsigned char RingBufRx[COMM_RX_BUF_SIZE]; /* Ring buffer character storage (Rx) */  
  14.     unsigned short RingBufTxCtr; /* Number of characters in the Tx ring buffer */  
  15.     OS_EVENT *RingBufTxSem; /* Pointer to Tx semaphore */  
  16.     unsigned char *RingBufTxInPtr; /* Pointer to where next character will be inserted */  
  17.     unsigned char *RingBufTxOutPtr; /* Pointer from where next character will be extracted */  
  18.     unsigned char RingBufTx[COMM_TX_BUF_SIZE]; /* Ring buffer character storage (Tx) */  
  19. } COMM_RING_BUF;  
  20.   
  21. /* 
  22.  * GLOBAL VARIABLES 
  23.  */  
  24. COMM_RING_BUF Comm1Buf;  
  25. COMM_RING_BUF Comm2Buf;  
  26.   
  27. static void COMEnableTxInt(unsigned char port)  
  28. {  
  29.     static USART_TypeDef* map[2] = {USART1, USART2};  
  30.     //USART_ITConfig(map[port], USART_IT_TXE, ENABLE);  
  31.     map[port]->CR1 |= USART_FLAG_TXE;  
  32. }  
  33.   
  34. /* 
  35. *************************************************** *************************************************** ***** 
  36. * REMOVE CHARACTER FROM RING BUFFER 
  37. * Description: This function is called by your application to obtain a character from the communications 
  38. * channel. The function will wait for a character to be received on the serial channel or 
  39. * until the function times out. 
  40. * Arguments: 'ch' is the COMM port channel number and can either be: 
  41. *COMM1 
  42. *COMM2 
  43. * 'to' is the amount of time (in clock ticks) that the calling function is willing to 
  44. * wait for a character to arrive. If you specify a timeout of 0, the function will 
  45. * wait forever for a character to arrive. 
  46. * 'err' is a pointer to where an error code will be placed: 
  47. * *err is set to COMM_NO_ERR if a character has been received 
  48. * *err is set to COMM_RX_TIMEOUT if a timeout occurred 
  49. * *err is set to COMM_BAD_CH if you specify an invalid channel number 
  50. * Returns: The character in the buffer (or NUL if a timeout occurred) 
  51. *************************************************** *************************************************** ***** 
  52. */  
  53.   
  54. unsigned char CommGetChar(unsigned char ch, unsigned short to, unsigned char *err)  
  55. {  
  56.     unsigned char c;  
  57.     unsigned char oserr;  
  58.     COMM_RING_BUF *pbuf;  
  59.     OS_CPU_SR cpu_sr;  
  60.   
  61.     switch(ch)  
  62.     { /* Obtain pointer to communications channel */  
  63.     case COM1:  
  64.         pbuf = &Comm1Buf;  
  65.         break;  
  66.   
  67.     case COM2:  
  68.         pbuf = &Comm2Buf;  
  69.         break;  
  70.   
  71.     default:  
  72.         *err = COMM_BAD_CH;  
  73.         return (NUL);  
  74.     }  
  75.     OSSemPend(pbuf->RingBufRxSem, to, &oserr); /* Wait for character to arrive */  
  76.     if (oserr == OS_TIMEOUT)  
  77.     { /* See if characters received within timeout*/  
  78.         *err = COMM_RX_TIMEOUT; /* No, return error code */  
  79.         return (NUL);  
  80.     }  
  81.     else  
  82.     {  
  83.         OS_ENTER_CRITICAL();  
  84.         pbuf->RingBufRxCtr--; /* Yes, decrement character count */  
  85.         c = *pbuf->RingBufRxOutPtr++; /* Get character from buffer */  
  86.         if(pbuf->RingBufRxOutPtr == &pbuf->RingBufRx[COMM_RX_BUF_SIZE])  
  87.         { /* Wrap OUT pointer */  
  88.             pbuf->RingBufRxOutPtr = &pbuf->RingBufRx[0];  
  89.         }  
  90.         OS_EXIT_CRITICAL();  
  91.         *err = COMM_NO_ERR;  
  92.         return (c);  
  93.     }  
  94. }  
  95.   
  96. void CommPutStr(unsigned char ch, uint8_t *str)  
  97. {  
  98.     while(0 != *str)  
  99.     {  
  100.         CommPutChar(ch, *str, 0);  
  101.         str++;  
  102.     }  
  103. }  
  104. static unsigned char COMGetTxChar(unsigned char ch, unsigned char *err)  
  105. {  
  106.     unsigned char c;  
  107.     COMM_RING_BUF *pbuf;  
  108.   
  109.     switch(ch)  
  110.     { /* Obtain pointer to communications channel */  
  111.     case COM1:  
  112.         pbuf = &Comm1Buf;  
  113.         break;  
  114.   
  115.     case COM2:  
  116.         pbuf = &Comm2Buf;  
  117.         break;  
  118.   
  119.     default:  
  120.         *err = COMM_BAD_CH;  
  121.         return (NUL);  
  122.     }  
  123.     if(pbuf->RingBufTxCtr > 0)  
  124.     { /* See if buffer is empty */  
  125.         pbuf->RingBufTxCtr--; /* No, decrement character count */  
  126.         c = *pbuf->RingBufTxOutPtr++; /* Get character from buffer */  
  127.         if(pbuf->RingBufTxOutPtr == &pbuf->RingBufTx[COMM_TX_BUF_SIZE])  
  128.         { /* Wrap OUT pointer */  
  129.             pbuf->RingBufTxOutPtr = &pbuf->RingBufTx[0];  
  130.         }  
  131.         OSSemPost(pbuf->RingBufTxSem); /* Indicate that character will be sent */  
  132.         *err = COMM_NO_ERR;  
  133.         return (c); /* Characters are still available */  
  134.     }  
  135.     else  
  136.     {  
  137.         *err = COMM_TX_EMPTY;  
  138.         return (NUL); /* Buffer is empty */  
  139.     }  
  140. }  
  141.   
  142. /* 
  143. *************************************************** *************************************************** ***** 
  144. * INITIALIZE COMMUNICATIONS MODULE 
  145. * Description: This function is called by your application to initialize the communications module. You 
  146. * must call this function before calling any other functions. 
  147. * Arguments : none 
  148. *************************************************** *************************************************** ***** 
  149. */  
  150.   
  151. void COMInit(void)  
  152. {  
  153.     COMM_RING_BUF *pbuf;  
  154.   
  155.     pbuf = &Comm1Buf; /* Initialize the ring buffer for COMM1 */  
  156.     pbuf->RingBufRxCtr = 0;  
  157.     pbuf->RingBufRxInPtr = &pbuf->RingBufRx[0];  
  158.     pbuf->RingBufRxOutPtr = &pbuf->RingBufRx[0];  
  159.     pbuf->RingBufRxSem = OSSemCreate(0);  
  160.     pbuf->RingBufTxCtr = 0;  
  161.     pbuf->RingBufTxInPtr = &pbuf->RingBufTx[0];  
  162.     pbuf->RingBufTxOutPtr = &pbuf->RingBufTx[0];  
  163.     pbuf->RingBufTxSem = OSSemCreate(COMM_TX_BUF_SIZE);  
  164.   
  165.     pbuf = &Comm2Buf; /* Initialize the ring buffer for COMM2 */  
  166.     pbuf->RingBufRxCtr = 0;  
  167.     pbuf->RingBufRxInPtr = &pbuf->RingBufRx[0];  
  168.     pbuf->RingBufRxOutPtr = &pbuf->RingBufRx[0];  
  169.     pbuf->RingBufRxSem = OSSemCreate(0);  
  170.     pbuf->RingBufTxCtr = 0;  
  171.     pbuf->RingBufTxInPtr = &pbuf->RingBufTx[0];  
  172.     pbuf->RingBufTxOutPtr = &pbuf->RingBufTx[0];  
  173.     pbuf->RingBufTxSem = OSSemCreate(COMM_TX_BUF_SIZE);  
  174. }  
  175.   
  176. /* 
  177. *************************************************** *************************************************** ***** 
  178. * SEE IF RX CHARACTER BUFFER IS EMPTY 
  179. * Description: This function is called by your application to see if any character is available from the 
  180. * communications channel. If at least one character is available, the function returns 
  181. * FALSE otherwise, the function returns TRUE. 
  182. * Arguments: 'ch' is the COMM port channel number and can either be: 
  183. *COMM1 
  184. *COMM2 
  185. * Returns: TRUE if the buffer IS empty. 
  186. * FALSE if the buffer IS NOT empty or you have specified an incorrect channel. 
  187. *************************************************** *************************************************** ***** 
  188. */  
  189.   
  190. unsigned char CommIsEmpty(unsigned char ch)  
  191. {  
  192.     unsigned char empty;  
  193.     COMM_RING_BUF *pbuf;  
  194.     OS_CPU_SR cpu_sr;  
  195.   
  196.     switch(ch)  
  197.     { /* Obtain pointer to communications channel */  
  198.     case COM1:  
  199.         pbuf = &Comm1Buf;  
  200.         break;  
  201.   
  202.     case COM2:  
  203.         pbuf = &Comm2Buf;  
  204.         break;  
  205.   
  206.     default:  
  207.         return (TRUE);  
  208.     }  
  209.     OS_ENTER_CRITICAL();  
  210.     if(pbuf->RingBufRxCtr > 0)  
  211.     { /* See if buffer is empty */  
  212.         empty = FALSE; /* Buffer is NOT empty */  
  213.     }  
  214.     else  
  215.     {  
  216.         empty = TRUE; /* Buffer is empty */  
  217.     }  
  218.     OS_EXIT_CRITICAL();  
  219.     return (empty);  
  220. }  
  221.   
  222.   
  223. /* 
  224. *************************************************** *************************************************** ***** 
  225. * SEE IF TX CHARACTER BUFFER IS FULL 
  226. * Description: This function is called by your application to see if any more characters can be placed 
  227. * in the Tx buffer. In other words, this function check to see if the Tx buffer is full. 
  228. * If the buffer is full, the function returns TRUE otherwise, the function returns FALSE. 
  229. * Arguments: 'ch' is the COMM port channel number and can either be: 
  230. *COMM1 
  231. *COMM2 
  232. * Returns: TRUE if the buffer IS full. 
  233. * FALSE if the buffer IS NOT full or you have specified an incorrect channel. 
  234. *************************************************** *************************************************** ***** 
  235. */  
  236.   
  237. unsigned char CommIsFull(unsigned char ch)  
  238. {  
  239.     unsigned char full;  
  240.     COMM_RING_BUF *pbuf;  
  241.     OS_CPU_SR cpu_sr;  
  242.   
  243.     switch(ch)  
  244.     { /* Obtain pointer to communications channel */  
  245.     case COM1:  
  246.         pbuf = &Comm1Buf;  
  247.         break;  
  248.   
  249.     case COM2:  
  250.         pbuf = &Comm2Buf;  
  251.         break;  
  252.   
  253.     default:  
  254.         return (TRUE);  
  255.     }  
  256.     OS_ENTER_CRITICAL();  
  257.     if(pbuf->RingBufTxCtr < COMM_TX_BUF_SIZE)  
  258.     { /* See if buffer is full */  
  259.         full = FALSE; /* Buffer is NOT full */  
  260.     }  
  261.     else  
  262.     {  
  263.         full = TRUE; /* Buffer is full */  
  264.     }  
  265.     OS_EXIT_CRITICAL();  
  266.     return (full);  
  267. }  
  268.   
  269. /* 
  270. *************************************************** *************************************************** ***** 
  271. * OUTPUT CHARACTER 
  272. * Description: This function is called by your application to send a character on the communications 
  273. * channel. The function will wait for the buffer to empty out if the buffer is full. 
  274. * The function returns to your application if the buffer doesn't empty within the specified 
  275. * timeout. A timeout value of 0 means that the calling function will wait forever for the 
  276. * buffer to empty out. The character to send is first inserted into the Tx buffer and will 
  277. * be sent by the Tx ISR. If this is the first character placed into the buffer, the Tx ISR 
  278. * will be enabled. 
  279. * Arguments: 'ch' is the COMM port channel number and can either be: 
  280. *COMM1 
  281. *COMM2 
  282. * 'c' is the character to send. 
  283. * 'to' is the timeout (in clock ticks) to wait in case the buffer is full. If you 
  284. * specify a timeout of 0, the function will wait forever for the buffer to empty. 
  285. * Returns: COMM_NO_ERR if the character was placed in the Tx buffer 
  286. * COMM_TX_TIMEOUT if the buffer didn't empty within the specified timeout period 
  287. * COMM_BAD_CH if you specify an invalid channel number 
  288. *************************************************** *************************************************** ***** 
  289. */  
  290.   
  291. unsigned char CommPutChar(unsigned char ch, unsigned char c, unsigned short to)  
  292. {  
  293.     unsigned char oserr;  
  294.     COMM_RING_BUF *pbuf;  
  295.     OS_CPU_SR cpu_sr;  
  296.   
  297.     switch(ch)  
  298.     { /* Obtain pointer to communications channel */  
  299.     case COM1:  
  300.         pbuf = &Comm1Buf;  
  301.         break;  
  302.   
  303.     case COM2:  
  304.         pbuf = &Comm2Buf;  
  305.         break;  
  306.   
  307.     default:  
  308.         return (COMM_BAD_CH);  
  309.     }  
  310.     OSSemPend(pbuf->RingBufTxSem, to, &oserr); /* Wait for space in Tx buffer */  
  311.     if (oserr == OS_TIMEOUT)  
  312.     {  
  313.         return (COMM_TX_TIMEOUT); /* Timed out, return error code */  
  314.     }  
  315.     OS_ENTER_CRITICAL();  
  316.     pbuf->RingBufTxCtr++; /* No, increment character count */  
  317.     *pbuf->RingBufTxInPtr++ = c; /* Put character into buffer */  
  318.     if(pbuf->RingBufTxInPtr == &pbuf->RingBufTx[COMM_TX_BUF_SIZE])  
  319.     { /* Wrap IN pointer */  
  320.         pbuf->RingBufTxInPtr = &pbuf->RingBufTx[0];  
  321.     }  
  322.     if(pbuf->RingBufTxCtr == 1)  
  323.     { /* See if this is the first character */  
  324.         COMEnableTxInt(ch); /* Yes, Enable Tx interrupts */  
  325.     }  
  326.     OS_EXIT_CRITICAL();  
  327.     return (COMM_NO_ERR);  
  328. }  
  329.   
  330.   
  331. /* 
  332. *************************************************** *************************************************** ***** 
  333. * INSERT CHARACTER INTO RING BUFFER 
  334. * Description: This function is called by the Rx ISR to insert a character into the receive ring buffer. 
  335. * Arguments: 'ch' is the COMM port channel number and can either be: 
  336. *COMM1 
  337. *COMM2 
  338. * 'c' is the character to insert into the ring buffer. If the buffer is full, the 
  339. * character will not be inserted, it will be lost. 
  340. *************************************************** *************************************************** ***** 
  341. */  
  342. static void COMPutRxChar(unsigned char ch, unsigned char c)  
  343. {  
  344.     COMM_RING_BUF *pbuf;  
  345.   
  346.   
  347.     switch(ch)  
  348.     { /* Obtain pointer to communications channel */  
  349.     case COM1:  
  350.         pbuf = &Comm1Buf;  
  351.         break;  
  352.   
  353.     case COM2:  
  354.         pbuf = &Comm2Buf;  
  355.         break;  
  356.   
  357.     default:  
  358.         return;  
  359.     }  
  360.     if(pbuf->RingBufRxCtr < COMM_RX_BUF_SIZE)  
  361.     { /* See if buffer is full */  
  362.         pbuf->RingBufRxCtr++; /* No, increment character count */  
  363.         *pbuf->RingBufRxInPtr++ = c; /* Put character into buffer */  
  364.         if(pbuf->RingBufRxInPtr == &pbuf->RingBufRx[COMM_RX_BUF_SIZE])  
  365.         { /* Wrap IN pointer */  
  366.             pbuf->RingBufRxInPtr = &pbuf->RingBufRx[0];  
  367.         }  
  368.         OSSemPost(pbuf->RingBufRxSem); /* Indicate that character was received */  
  369.     }  
  370. }  
  371. // This function is called by the Rx ISR to insert a character into the receive ring buffer.  
  372.   
  373.   
  374. void USART1_IRQHandler(void)  
  375. {  
  376.     unsigned int data;  
  377.     unsigned char err;  
  378.     OS_CPU_SR cpu_sr;  
  379.   
  380.     OS_ENTER_CRITICAL(); /* Tell uC/OS-II that we are starting an ISR */  
  381.     OSIntNesting++;  
  382.     OS_EXIT_CRITICAL();  
  383.   
  384.     if(USART1->SR & 0x0F)  
  385.     {  
  386.         // See if we have some kind of error  
  387.         // Clear interrupt (do nothing about it!)  
  388.         data = USART1->DR;  
  389.     }  
  390.     else if(USART1->SR & USART_FLAG_RXNE) //Receive Data Reg Full Flag  
  391.     {  
  392.         data = USART1->DR;  
  393.         COMPutRxChar(COM1, data); // Insert received character into buffer  
  394.     }  
  395.     else if(USART1->SR & USART_FLAG_TXE)  
  396.     {  
  397.         data = COMGetTxChar(COM1, &err); // Get next character to send.  
  398.         if (err == COMM_TX_EMPTY)  
  399.         { // Do we have anymore characters to send?  
  400.             // No, Disable Tx interrupts  
  401.             //USART_ITConfig(USART1, USART_IT_TXE| USART_IT_TC, DISABLE);  
  402.             USART1->CR1 &= ~USART_FLAG_TXE | USART_FLAG_TC;  
  403.         }  
  404.         else  
  405.         {  
  406.             USART1->DR = data; // Yes, Send character  
  407.         }  
  408.     }  
  409.     OSIntExit();  
  410. }  
  411.   
  412. void USART2_IRQHandler(void)  
  413. {  
  414.     unsigned int data;  
  415.     unsigned char err;  
  416.     OS_CPU_SR cpu_sr;  
  417.   
  418.     OS_ENTER_CRITICAL(); /* Tell uC/OS-II that we are starting an ISR */  
  419.     OSIntNesting++;  
  420.     OS_EXIT_CRITICAL();  
  421.   
  422.     if(USART2->SR & 0x0F)  
  423.     {  
  424.         // See if we have some kind of error  
  425.         // Clear interrupt (do nothing about it!)  
  426.         data = USART2->DR;  
  427.     }  
  428.     else if(USART2->SR & USART_FLAG_RXNE) //Receive Data Reg Full Flag  
  429.     {  
  430.         data = USART2->DR;  
  431.         COMPutRxChar(COM2, data); // Insert received character into buffer  
  432.     }  
  433.     else if(USART2->SR & USART_FLAG_TXE)  
  434.     {  
  435.         data = COMGetTxChar(COM2, &err); // Get next character to send.  
  436.         if (err == COMM_TX_EMPTY)  
  437.         { // Do we have anymore characters to send?  
  438.             // No, Disable Tx interrupts  
  439.             //USART_ITConfig(USART2, USART_IT_TXE| USART_IT_TC, DISABLE);  
  440.             USART2->CR1 &= ~USART_FLAG_TXE | USART_FLAG_TC;  
  441.         }  
  442.         else  
  443.         {  
  444.             USART2->DR = data; // Yes, Send character  
  445.         }  
  446.     }  
  447.     OSIntExit();  
  448. }  

 

Here is another test code:

  1. #include "stm32f10x.h"  
  2. #include "uart.h"  
  3. #include "led.h"  
  4. #include "COMMRTOS.H"  
  5. #include "ucos_ii.h"  
  6.   
  7. #define TASK_STK_SIZE 128  
  8. OS_STK TaskStartStk[TASK_STK_SIZE];  
  9. OS_STK TaskUartReadStk[TASK_STK_SIZE];  
  10.   
  11. void TaskUartRead(void *pdata)  
  12. {  
  13.     unsigned char err;  
  14.     unsigned char c;  
  15.   
  16.     for(;;)  
  17.     {  
  18.         c = CommGetChar(COM2, 0, &err);  
  19.         if (err == COMM_NO_ERR)  
  20.             CommPutChar(COM2, c, 0);  
  21.     }  
  22. }  
  23. void TaskStart(void *pdata)  
  24. {  
  25.     SysTick_Config(SystemCoreClock/10);  
  26.     USART1_Init();  
  27.     USART2_Init();  
  28.     COMInit();  
  29.     //USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);  
  30.     //USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);  
  31.     USART1->CR1 |= USART_FLAG_RXNE;  
  32.     USART2->CR1 |= USART_FLAG_RXNE;  
  33.   
  34.     OSTaskCreate(TaskUartRead, (void *)0, &(TaskUartReadStk[TASK_STK_SIZE-1]), 2);  
  35.   
  36.     UART_PutStr (USART2, "USART2 Hello World!\n\r");  
  37.     //CommPutChar(COM2, '+', 0);  
  38.     CommPutStr(COM2, "CommPutCharB\n\r");  
  39.     for(;;)  
  40.     {  
  41.         LED_Spark();  
  42.         CommPutChar(COM2, '+', 0);  
  43.         OSTimeDly(10);  
  44.     }  
  45. }  
  46.   
  47. int main(void)  
  48. {  
  49.     SystemInit();  
  50.     LED_Init();  
  51.     OSInit();  
  52.     OSTaskCreate(TaskStart, (void *)0, &(TaskStartStk[TASK_STK_SIZE-1]), 1);  
  53.     OSStart();  
  54.     for(;;)  
  55.     {  
  56.   
  57.     }     
  58. }  
  59.  

Keywords:STM32F10x  USART Reference address:STM32F10x study notes 7 (USART realizes serial communication 3)

Previous article:STM32F10x Study Notes 8 (USART implements serial communication DMA method)
Next article:STM32F10x Study Notes 7 (Independent Watchdog IWDG Module)

Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号