Setting the output mode and cfg on a STM32F103 - Page 1
Forum section: electronics / general

author: kenn
author_rank: Contributor
timestamp: April 26, 2017, 04:47:54 am
content: Hi there,Is there anyone out here who would be familiar with programming the STM32f103x in C++? I am working in eclipse and trying to teach myself about micro-controllers and while I find a lot of examples about the STM32F0xx the 103 seems to be a little different - the upside is I really have to understand it as opposed to just copy and pasting some code. With that said I wondering if I am correct about the code I have written so far. I am trying to set port A:1 up to do push pull output and this is what I have so far.//enable GPOI clock for port A using AHB and RCC registersRCC->APB2ENR |= RCC_APB2ENR_IOPAEN;//Set any control registers for PortA Pin 1GPIOA->CRL |= GPIO_CRL_MODE1;//Set the typeGPIOA->ODR |= (GPIO_ODR_ODR2);GPIOA->ODR |= (GPIO_ODR_ODR3);//I believe the result of all this would be 0000 0000 0000 0000 0000 0000 0000 0000 0011 1100 in the register for gpio ABasically I was hoping someone could tell me "Yes, you are on the right track" or "No way - you are totally wrong" and if the later is the case then why.Thanks a lot!

author: westfw
author_rank: Super Contributor
timestamp: April 26, 2017, 09:24:54 am
content: QuoteIt's not clear whether you understand that GPIO_CRL_MODE1 is a bitmask of the MODE bits for pin1, so you're setting both bits to 1 here. Also, you're NOT setting the CNF bits that are in the same register. Assuming that they start out at 0, this will give you the bit set for 50MHz push-pull output, which is probably what you actually want, anyway. But even in assembly language (https://github.com/WestfW/Minimal-ARM/blob/master/Blink/blink.S#L132)I made it say:Code:((GPIO_MODE_OUT+GPIO_CNF_PP) << (mybit*4))(Alas, it looks like I had to create those constants; I don't see them in the stm32f10x.h file, or the documentation :-( )Quote"Set the type"?? ODR is the output data register, and the various ODR_ODR2 are just names for the individual bits.So, having lucked out in setting pin1 to be an output, you appear to be writing to pins 2 and 3. Probably not what you had in mind.QuoteWhich register are you talking about?The STM32f10x chips only have 16 pins associated with each GPIO port, and the CRL register had 4 bits for each of the first 8 pins, so for a fast push-pull output on pin 1, you WANT (probably)CRL = 0000 0000 0000 0000 0000 0000 0000 000000110000 // mode =11, cnf = 00. Other bits left at 0.

author: Jeroen3
author_rank: Super Contributor
timestamp: April 26, 2017, 09:58:02 am
content: I recommended explicitly setting all IO.Code:// CNF#define I_AN 0u // Input Analog#define I_FL 1u // Input Float#define I_DI 2u // Input Pull-up/down#define O_PP 0u // Output push-pull#define O_OD 1u // Output open-drain#define A_PP 2u // Periph push-pull#define A_OD 3u // Periph open-drain// MODE#define INPUT 0u // Input#define OUT_S 1u // Slow output#define OUT_M 2u // Medium output#define OUT_F 3u // Fast outputGPIOA->CRH =/*15*/ (A_PP << GPIO_CRH_CNF15_Pos)|(OUT_S << GPIO_CRH_MODE15_Pos)| ///*14*/ (A_PP << GPIO_CRH_CNF14_Pos)|(OUT_S << GPIO_CRH_MODE14_Pos)| ///*13*/ (O_OD << GPIO_CRH_CNF13_Pos)|(OUT_S << GPIO_CRH_MODE13_Pos)| ///*12*/ (O_PP << GPIO_CRH_CNF12_Pos)|(OUT_S << GPIO_CRH_MODE12_Pos)| ///*11*/ (I_DI << GPIO_CRH_CNF11_Pos)|(INPUT << GPIO_CRH_MODE11_Pos)| ///*10*/ (I_AN << GPIO_CRH_CNF10_Pos)|(OUT_S << GPIO_CRH_MODE10_Pos)| ///*09*/ (I_FL << GPIO_CRH_CNF9_Pos)| (INPUT << GPIO_CRH_MODE9_Pos)| ///*08*/ (I_AN << GPIO_CRH_CNF8_Pos)| (OUT_S << GPIO_CRH_MODE8_Pos); //GPIOA->CRL =/*07*/ (I_AN << GPIO_CRL_CNF7_Pos)| (INPUT << GPIO_CRL_MODE7_Pos)| ///*06*/ (I_AN << GPIO_CRL_CNF6_Pos)| (INPUT << GPIO_CRL_MODE6_Pos)| ///*05*/ (I_AN << GPIO_CRL_CNF5_Pos)| (INPUT << GPIO_CRL_MODE5_Pos)| ///*04*/ (I_AN << GPIO_CRL_CNF4_Pos)| (INPUT << GPIO_CRL_MODE4_Pos)| ///*03*/ (I_AN << GPIO_CRL_CNF3_Pos)| (INPUT << GPIO_CRL_MODE3_Pos)| ///*02*/ (I_AN << GPIO_CRL_CNF2_Pos)| (INPUT << GPIO_CRL_MODE2_Pos)| ///*01*/ (I_AN << GPIO_CRL_CNF1_Pos)| (INPUT << GPIO_CRL_MODE1_Pos)| ///*00*/ (I_AN << GPIO_CRL_CNF0_Pos)| (INPUT << GPIO_CRL_MODE0_Pos); //#define PIN_HIGH +0u#define PIN_LOW +16uGPIOA->BSRR =(1u << (0 PIN_LOW))|(1u << (1 PIN_LOW))|(1u << (2 PIN_LOW))|(1u << (3 PIN_LOW))|(1u << (4 PIN_LOW))|(1u << (5 PIN_LOW))|(1u << (6 PIN_LOW))|(1u << (7 PIN_LOW))|(1u << (8 PIN_LOW))|(1u << (9 PIN_LOW))|(1u << (10 PIN_LOW))|(1u << (11 PIN_HIGH))|(1u << (12 PIN_LOW))|(1u << (13 PIN_LOW))|(1u << (14 PIN_LOW))|(1u << (15 PIN_LOW));

author: kenn
author_rank: Contributor
timestamp: April 26, 2017, 01:33:57 pm
content: Thanks for the responses, and yes, I realized that I was indeed setting the configuration bits on the wrong pin.Forgetting the programming and what I have already done for a moment is it correct that the 4 bits I care about are 4 5 6 and 7? They control pin one I believe. With that said if I simply set bit four to 1 and 5 6 and 7 where 0 I would be setting pin 1 with an output with a max speed of 10mhz and then bits 5 and 6 would be read as General purpose output push-pull because the mode was output. I think I am right about that.Here is the PDF I am looking at, it's page 170 - see the attached image as well.http://www.st.com/content/ccc/resource/technical/document/reference_manual/59/b9/ba/7f/11/af/43/d5/CD00171190.pdf/files/CD00171190.pdf/jcr:content/translations/en.CD00171190.pdf

author: westfw
author_rank: Super Contributor
timestamp: April 26, 2017, 10:06:08 pm
content: Quoteyes, that seems correct.In principle, I like Jeroen3's suggestion that you set ALL the bits. But in practice that seems to be one of the main reasons that ARM Vendor library code tends to be bloated - they really make use of that 32bit address space, and there are a LOT of registers to set, if you insist on setting them all rather than believing in the "default power-on values." (In this particular case, it wouldn't be a big deal, especially done as Jeroen3 shows...)

author: kenn
author_rank: Contributor
timestamp: April 27, 2017, 02:17:06 am
content: Thank you very much, at least I understand the concept with that I can figure out the code, the nice thing is that I already have experience with openOCD and debugging shouldn't be an issue, it will be fun but there is still a few more things to sort out.