// ****************************************************************************************** // Project : STM32VLDISCOVERY Sample Program (STM32F100RB) // Program Name : // Programer : // Create date : Version 1.0 H24.10.02 // History : // Laungage : // ****************************************************************************************** // Description // Fck : 24MHz(PLL) // USART : TX1:A9, RX1:A10 // A/D Converter : ADC1-IN0(A0) // ****************************************************************************************** #include #include #include #include "stm32f10x.h" void Init_clock(unsigned char); void InitUART(void); void SendUARTStr(unsigned char *); void SendUART(unsigned char ); void RecUART(unsigned char *); void InitADC(void); void GetADC(unsigned int *); void Editdata(unsigned char *,unsigned int); void wait(void); #define PI_DATALINE_MAX 100 #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 int adc_data; unsigned char TMP_dataline[PI_DATALINE_MAX]; // ******************* // 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 24.000[MHz] // (1)Define APB2(peripheral clock enable register) RCC->APB2ENR = 0x00004205; // Clock enable (Alternate Function I/O clock enable[0], I/O port A clock enable[2], // USART1 clock enable[14], ADC 1 interface clock enable[9]) // (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 = 0x44444444; // Port configuration register low (GPIOA[0-7]) // 4: CNF=01:Floating input (reset state), MODE=00:Input mode (reset state) GPIOA->CRH = 0x444444B4; // Port configuration register high(GPIOA[8-15]) // B: 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)Initialize A/D Converter InitADC(); // (6)Put Message SendUARTStr(" STM32VLDISCOVERY Connected OK> "); // ******************* // 2.Program Main // ******************* while(1){ // (1)Get A/D conveter data GetADC(&adc_data); // (2)Edit data format Editdata(TMP_dataline, adc_data); // (3)Display A/D conveter data SendUARTStr(TMP_dataline); // (4)Wait wait(); } } //****************************************************************************************** // Function Name : InitUART // Title : Initialized UART // Input : // Output : //****************************************************************************************** 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 * // * Fck:8[MHz] , Baud-rate:9600BPS * // * BRR : 8000000 / (9600 * 16) ==> 52.083 * // * BRR[15:4] : 52 <== int(156.25) * // * BRR[3:0] : 1 <== 16 * 0.083 * // ------------------------------------------------------------------------ // USART1->BRR = ( 156 << 4 ) | 4 ; USART1->BRR = ( 52 << 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 : InitADC // Title : Initialize A/D Converter // Input : // Output : // Description : A/D Converter : ADC1-IN0(A0) //****************************************************************************************** void InitADC(void) { // *************************************** // Define ADC_CR2( ADC control register 2 ) // *************************************** // ADC_CR2[31:24] Reserved // ADC_CR2[23] TSVREFE: Temperature sensor and VREFINT enable // ADC_CR2[22] SWSTART: Start conversion of regular channels // ADC_CR2[21] JSWSTART: Start conversion of injected channels // ADC_CR2[20] EXTTRIG: External trigger conversion mode for regular channels // ADC_CR2[19:17] EXTSEL[2:0]: External event select for regular group // ADC_CR2[16] Reserved // ADC_CR2[15] JEXTTRIG: External trigger conversion mode for injected channels // ADC_CR2[14:12] JEXTSEL[2:0]: External event select for injected group // ADC_CR2[11] ALIGN: Data alignment // 0: Right Alignment, 1: Left Alignment // ADC_CR2[10:9] Reserved, must be kept cleared. // ADC_CR2[8] DMA // ADC_CR2[7:4] Reserved, must be kept cleared. // ADC_CR2[3] RSTCAL: Reset calibration // ADC_CR2[2] CAL: A/D Calibration // ADC_CR2[1] CONT: Continuous conversion // ADC_CR2[0] ADON: A/D converter ON / OFF // If this bit holds a value of zero and a 1 is written to it then it wakes up the ADC from Power Down state. // Conversion starts when this bit holds a value of 1 and a 1 is written to it. // 0: Disable ADC conversion/calibration and go to power down mode. // 1: Enable ADC and to start conversion ADC1->CR2 = 0x00000000; // *************************************** // Define ADC_SQR3( ADC regular sequence register 3 ) // *************************************** // ADC_SQR3[31:30] Reserved. // ADC_SQR3[29:25] SQ6[4:0]: 6th conversion in regular sequence // These bits are written by software with the channel number (0..17) assigned as the 6th in the sequence to be converted. // ADC_SQR3[24:20] SQ5[4:0]: 5th conversion in regular sequence // ADC_SQR3[19:15] SQ4[4:0]: 4th conversion in regular sequence // ADC_SQR3[14:10] SQ3[4:0]: 3rd conversion in regular sequence // ADC_SQR3[9:5] SQ2[4:0]: 2nd conversion in regular sequence // ADC_SQR3[4:0] SQ1[4:0]: 1st conversion in regular sequence ADC1->SQR3 =0x00000001; //1st conversion ADC1-IN0 // *************************************** // Define ADC_SQR1( ADC regular sequence register 1 ) // *************************************** // ADC_SQR3[31:24] Reserved, must be kept cleared. // ADC_SQR3[23:20] L[3:0]: Regular channel sequence length // These bits are written by software to define the total number of conversions in the regular channel conversion sequence. // 0000: 1 conversion // 0001: 2 conversions // **** // 1111: 16 conversions // ADC_SQR3[19:15] SQ16[4:0]: 16th conversion in regular sequence // These bits are written by software with the channel number (0..17) assigned as the 16th in the conversion sequence. // ADC_SQR3[14:10] SQ15[4:0]: 15th conversion in regular sequence // ADC_SQR3[9:5] SQ14[4:0]: 14th conversion in regular sequence // ADC_SQR3[4:0] SQ13[4:0]: 13th conversion in regular sequence ADC1->SQR3 =0x00000000; //1 conversion // *************************************** // A/D converter ON // *************************************** ADC1->CR2 |= 0x00000001; } //****************************************************************************************** // Function Name : GetADC // Title : Get A/D Converter data // Input : // Output : // Description : AD1 //****************************************************************************************** void GetADC(unsigned int *adc_data) { ADC1->CR2 |= 0x00000001; //Enable ADC and to start conversion while ((ADC1->SR & 0x00000002) == 0); //ADC_SR(ADC status register)[1]:EOC: End of conversion //This bit is set by hardware at the end of a group channel conversion (regular or injected). //It is cleared by software or by reading the ADC_DR. // 0: Conversion is not complete, 1: Conversion complete *adc_data = (unsigned int)(ADC1->DR & 0x00000fff); //ADC_DR(ADC regular data register) 12bit // ADC_DR[31:16] Reserved // ADC_DR[15:0] Regular data } //****************************************************************************************** // Function Name : Editdata // Title : Edit data format // Input : // Output : //****************************************************************************************** void Editdata(unsigned char put_str[],unsigned int adc_data) { unsigned int volt_data; strcpy(&put_str[0]," "); volt_data = adc_data * 3300 / 4095 ; sprintf(&put_str[2],"%d",volt_data); strcat(&put_str[0],"[mV] "); } //****************************************************************************************** // 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; } } //**************************************************************************** // Function Name : wait // Title : // Input : // Output : // Description : //**************************************************************************** void wait() { unsigned int lp,lp1; for(lp=0;lp<10000;lp++) for(lp1=0;lp1<100;lp1++){}; }