// ****************************************************************************************** // Project : STM32F103C8T6 Sample Program // Program Name : // Programer : // Create date : Version 1.0 H30.07.17 // History : // Laungage : Atollic TrueSTDIO C Launguage // ****************************************************************************************** // Description // Fck : 24MHz (PLL Clock) // USART : TX1:A9, RX1:A10 // ****************************************************************************************** #include "stm32f10x.h" void Init_clock(unsigned char); void InitUART(void); void SendUARTStr(unsigned char *); void SendUART(unsigned char ); void RecUART(unsigned char *); #define PI_HSI_SYSCLK 1 //HSI clock selected #define PI_HSE_SYSCLK 2 //HSE clock selected #define PI_PLL_SYSCLK 3 //PLL clock selected int main(void) { unsigned char IO_char; // ******************* // 1.Initialize // ******************* // (0)Define Clock // Init_clock(PI_HSI_SYSCLK); // HSI clock 8 [MHz] // Init_clock(PI_HSE_SYSCLK); // HSE clock 8.000[MHz] Init_clock(PI_PLL_SYSCLK); // PLL clock 72.000[MHz] // (1)Define APB2(peripheral clock enable register) RCC->APB2ENR = 0x00004005; // Clock enable (Alternate Function I/O clock enable[0], I/O port A clock enable[2], // USART1@ clock enable[14]) // (2)Define AFIO_MAPR(AF remap and debug I/O configuration register) // AFIO_MAPR // AFIO_MAPR[2]:USART1_REMAP 0: No remap (TX/PA9, RX/PA10), 1: Remap (TX/PB6, RX/PB7) // Reset value: 0x00000000 // (3)Define I/O Port A // GPIOA->CRL // Port configuration register low (GPIOA[0-7]) GPIOA->CRH = 0x444444B4; // Port configuration register high(GPIOA[8-15]) // 1: CNF=10:Alternate function output Push-pull, MODE=11:Output mode, max speed 50 MHz. // 4: CNF=01:Floating input (reset state), MODE=00:Input mode (reset state) // GPIOA->IDR // Port input data register (Read Only) IDR[31-16]:Reserved,@IDR[15-0]:Port output data // GPIOA->ODR // Port output data register ODR[31-16]:Reserved,@ODR[15-0]:Port output data // GPIOA->BSRR // Port bit set/reset registe // GPIOA->BRR // Port bit reset register // GPIOA->LCKR // Port configuration lock register // (4)Initialize UART InitUART(); // (5)Put Message SendUARTStr((unsigned char *)" STM32F103C8T6 Connected OK> "); // ******************* // 2.Program Main // ******************* while(1){ RecUART(&IO_char); SendUART(IO_char); } } //****************************************************************************************** // Function Name : InitUART // Title : Initialized UART // Input : // Output : // Description : Sysclock 24[MHz] //****************************************************************************************** void InitUART(void) { // *************************************** // 1.Define BRR( Baud rate register ) // *************************************** // BRR[31:16] Reserved // BRR[15:4] DIV_Mantissa[11:0]: mantissa of USARTDIV // These 12 bits define the mantissa of the USART Divider (USARTDIV) // BRR[3:0] DIV_Fraction[3:0]: fraction of USARTDIV // These 4 bits define the fraction of the USART Divider (USARTDIV). // When OVER8=1, the DIV_Fraction3 bit is not considered and must be kept cleared. // // ------------------------------------------------------------------------ // * Examples: =>See. Manual p.754 * // * BRR = Fck / ( Baud-rate * 16 ) * // * Fck:24[MHz] (8MHz[Crystal] * 3[PLL]), Baud-rate:9600BPS * // * BRR : 8000000 * 3 / (9600 * 16) ==> 156.25 * // * BRR[15:4] : 156 <== int(156.25) * // * BRR[3:0] : 4 <== 16 * 0.25 * // * BRR : 36000000 / (9600 * 16) ==> 234.375 * // * BRR[15:4] : 234 <== int(234.375) * // * BRR[3:0] : 6 <== 16 * 0.375 // * BRR : 8000000 / (9600 * 16) ==> 52.0833 * // * BRR[15:4] : 52 <== int(52.0833) * // * BRR[3:0] : 1 <== 16 * 0.0833 * // * BRR : 72000000 / (9600 * 16) ==> 468.75 * // * BRR[15:4] : 468 <== int(468.75) * // * BRR[3:0] : 12 <== 16 * 0.75 * // * BRR : 72000000 / (115200 * 16) ==> 39.0625 * // * BRR[15:4] : 39 <== int(39.0625) * // * BRR[3:0] : 1 <== 16 * 0.0625 * // ------------------------------------------------------------------------ USART1->BRR = ( 39 << 4 ) | 1 ; // *************************************** // 2.Define CR1( Control register 1 ) // *************************************** // CR1[31:16] Reserved, // CR1[15] OVER8 : Oversampling mode 0: oversampling by 16, 1: oversampling by 8 // CR1[14] Reserved // CR1[13] UE: USART enable 0: USART prescaler and outputs disabled, 1: USART enabled // CR1[12] M: Word length 0: 1 Start bit, 8 Data bits, n Stop bit, 1: 1 Start bit, 9 Data bits, n Stop bit // CR1[11] WAKE: Wakeup method 0: Idle Line, 1: Address Mark // CR1[10] PCE: Parity control enable 0: Parity control disabled, 1: Parity control enabled // CR1[9] PS: Parity selection 0: Even parity, 1: Odd parity // CR1[8] PEIE: PE interrupt enable 0: Interrupt is inhibited, 1: An USART interrupt is generated whenever PE=1 in the USART_SR register // CR1[7] TXEIE: TXE interrupt enable // CR1[6] TCIE: Transmission complete interrupt enable 0: Interrupt is inhibited, 1: An USART interrupt is generated whenever TC=1 in the USART_SR register // CR1[5] RXNEIE: RXNE interrupt enable 0: Interrupt is inhibited, 1: An USART interrupt is generated whenever ORE=1 or RXNE=1 in the USART_SR register // CR1[4] IDLEIE: IDLE interrupt enable 0: Interrupt is inhibited, 1: An USART interrupt is generated whenever IDLE=1 in the USART_SR register // CR1[3] TE: Transmitter enable 0: Transmitter is disabled, 1: Transmitter is enabled // CR1[2] RE: Receiver enable 0: Receiver is disabled, 1: Receiver is enabled and begins searching for a start bit // CR1[1] RWU: Receiver wakeup // CR1[0] SBK: Send break 0: No break character is transmitted, 1: Break character will be transmitted USART1->CR1 = 0x00000000; USART1->CR1 |= 0x0000000C; //TE[3],RE[2] Transmitter is enabled, Reciver is enabled USART1->CR1 |= 0x00002000; //UE[13] USART enabled } //****************************************************************************************** // Function Name : SendUARTStr // Title : Send UART Strings // Input : // Output : //****************************************************************************************** void SendUARTStr(unsigned char in_s[]) { unsigned char lp = 0; while(in_s[lp] != 0){ SendUART(in_s[lp]); lp++; } } //****************************************************************************************** // Function Name : SendUART // Title : Send UART // Input : // Output : //****************************************************************************************** void SendUART(unsigned char in_c) { while (!(USART1->SR & 0x0080)); // SR[7]:TXE: Transmit data register empty // 0: Data is not transferred to the shift register, // 1: Data is transferred to the shift register USART1->DR = in_c; // Data register DR[31:9]:Reserved, DR[8:0]: Data value } //****************************************************************************************** // Function Name : RecUART // Title : Recive UART // Input : // Output : //****************************************************************************************** void RecUART(unsigned char *out_c) { while (!(USART1->SR & 0x0020)); // SR[5]:RXNE Read data register not empty // 0: Data is not received 1: Received data is ready to be read. *out_c =(unsigned char)(USART1->DR & 0xFF); // Data register DR[31:9]:Reserved, DR[8:0]: Data value } //****************************************************************************************** // Function Name : Init_clock // Title : Initialized System clock // Input : // Output : // Description : //****************************************************************************************** void Init_clock(unsigned char clk_mode) { // ***************************************** // RCC_CFGR(Clock configuration register) Reset value: 0x0000 0000 // ***************************************** // RCC_CFGR[31:27] Reserved, always read as 0. // RCC_CFGR[26:24] MCO: Microcontroller clock output // Set and cleared by software. // 0xx: No clock // 100: System clock (SYSCLK) selected // 101: HSI clock selected // 110: HSE clock selected // 111: PLL clock divided by 2 selected // This clock output may have some truncated cycles at startup or during MCO clock source switching. // RCC_CFGR[23:22] Reserved. // RCC_CFGR[21:18] PLLMUL: PLL multiplication factor // These bits are written by software to define the PLL multiplication factor. // These bits can be written only when PLL is disabled. // Caution: The PLL output frequency must be in the 16-24 MHz range. // 0000: PLL input clock x 2 // 0001: PLL input clock x 3 // 0010: PLL input clock x 4 // 0011: PLL input clock x 5 // 0100: PLL input clock x 6 // 0101: PLL input clock x 7 // 0110: PLL input clock x 8 // 0111: PLL input clock x 9 // 1000: PLL input clock x 10 // 1001: PLL input clock x 11 // 1010: PLL input clock x 12 // 1011: PLL input clock x 13 // 1100: PLL input clock x 14 // 1101: PLL input clock x 15 // 1110: PLL input clock x 16 // 1111: PLL input clock x 16 // RCC_CFGR[17] PLLXTPRE: LSB of division factor PREDIV1 // Set and cleared by software to select the least significant bit of the PREDIV1 division factor. // It is the same bit as bit 0 in the RCC_CFGR2 register, so modifying bit 0 in the RCC_CFGR2 register changes this bit accordingly. // If bits[3:1] in the RCC_CFGR2 register are not set, the PLLXTPRE bit controls if PREDIV1 divides its input clock by 2 (PLLXTPRE=1) or not (PLLXTPRE=0). // This bit can be written only when the PLL is disabled. // RCC_CFGR[16] PLLSRC: PLL entry clock source // Set and cleared by software to select PLL clock source. // This bit can be written only when PLL is disabled. // 0: HSI oscillator clock / 2 selected as PLL input clock // 1: Clock from PREDIV1 selected as the PLL input clock // RCC_CFGR[15:14] ADCPRE: ADC prescaler // Set and cleared by software to select the frequency of the clock to ADC1. // 00: PLCK2 divided by 2 // 01: PLCK2 divided by 4 // 10: PLCK2 divided by 6 // 11: PLCK2 divided by 8 // RCC_CFGR[13:11] PPRE2: APB high-speed prescaler (APB2) // Set and cleared by software to control the division factor of the APB high-speed clock (PCLK2). // 0xx: HCLK not divided // 100: HCLK divided by 2 // 101: HCLK divided by 4 // 110: HCLK divided by 8 // 111: HCLK divided by 16 // RCC_CFGR[10:8] PPRE1: APB low-speed prescaler (APB1) // Set and cleared by software to control the division factor of the APB low-speed clock (PCLK1). // Warning: the software has to set correctly these bits to not exceed 36 MHz on this domain. // 0xx: HCLK not divided // 100: HCLK divided by 2 // 101: HCLK divided by 4 // 110: HCLK divided by 8 // 111: HCLK divided by 16 // RCC_CFGR[7:4] HPRE: AHB prescaler // Set and cleared by software to control the division factor of the AHB clock. // 0xxx: SYSCLK not divided // 1000: SYSCLK divided by 2 // 1001: SYSCLK divided by 4 // 1010: SYSCLK divided by 8 // 1011: SYSCLK divided by 16 // 1100: SYSCLK divided by 64 // 1101: SYSCLK divided by 128 // 1110: SYSCLK divided by 256 // 1111: SYSCLK divided by 512 // RCC_CFGR[3:2] SWS: System clock switch status // Set and cleared by hardware to indicate which clock source is used as system clock. // 00: HSI oscillator used as system clock // 01: HSE oscillator used as system clock // 10: PLL used as system clock // 11: not applicable // RCC_CFGR[1:0] SW: System clock switch // Set and cleared by software to select SYSCLK source. // Set by hardware to force HSI selection when leaving Stop and Standby mode or in case of // failure of the HSE oscillator used directly or indirectly as system clock (if the Clock Security System is enabled). // 00: HSI selected as system clock // 01: HSE selected as system clock // 10: PLL selected as system clock // 11: not allowed switch (clk_mode){ case PI_HSI_SYSCLK : RCC->CFGR = 0x00000000; break; case PI_HSE_SYSCLK : RCC->CFGR = 0x00000001; break; case PI_PLL_SYSCLK : RCC->CFGR = 0x00000002; break; default: RCC->CFGR = 0x00000000; } }