Dallas, Texas
Offline
God Member
Karma: 1
Posts: 689
Old, decrepit curmugeon
|
 |
« Reply #15 on: June 05, 2012, 04:38:41 pm » |
a uint32_t is the same as an unsigned long (not long) on the arduino... Other platforms may not have the same equivalence.
The captital in the typedef above is simply a means of using the term typedef as part of the variable name, when the keyword typedef is use in c/c++ it is a way of assigning a synonym to an existing data type.
|
|
|
|
|
Logged
|
|
|
|
|
SF Bay Area (USA)
Offline
Faraday Member
Karma: 78
Posts: 5454
Strongly opinionated, but not official!
|
 |
« Reply #16 on: June 05, 2012, 04:49:33 pm » |
So am I right that a uint32_t is identical to an Int i.e both 32 bits long so no difference at all On an ARM, yes. On an AVR, they would be different sizes. If you wanted to hold something like an IP address (32bits for v4), you could use an "int" on an ARM, but you'd have to use a "long" on an AVR: an incompatibility. Instead, your program should use "uint32_t" for the IP address, and it would run on both AVR and ARM (assuming all other architectural dependencies are fixed as well.) "typedef" defines a name that acts like a type (ie like "int" or "long"); it's a shorthand convenience, especially when you get to more complex structures (containing other structures, etc.) So someplace in an AVR include file there is likely to be a line that looks like: typedef unsigned long uint32_t; that means "treat the name "uint32_t" as a variable type, that is the same as "unsigned long". The similar file on an ARM might contain "t ypedef unsigned int uint32_t;" typedef uint32_t ip_addr_t;
typedef struct ip_pheader {ip_addr_t phdr_ip; uint16_t phdr_sourceport; uint16_t phdr_destport;} ip_pheader_t;
typedef struct socket {ip_pheader_t socket_local; ip_pheader_t socket_remote; uint32_t socket_timestamp; // etc } socket_t;
int open_socket (socket_t *s) { // code } is somewhat clearer than having to having to include the "struct xxx yyy" at each point. I don't know anything about "Typedef" with a capital T. As wanderson noted, there are all sorts of (local) conventions to indentifying a type as such, and coming up with a name that is easy to understand.
|
|
|
|
|
Logged
|
|
|
|
|
Dallas, Texas
Offline
God Member
Karma: 1
Posts: 689
Old, decrepit curmugeon
|
 |
« Reply #17 on: June 05, 2012, 05:31:34 pm » |
So am I right that a uint32_t is identical to an Int i.e both 32 bits long so no difference at all On an ARM, yes. On an AVR, they would be different sizes. Even on the ARM wouldn't uint32_t be an unsigned value, int be a signed value? So while they would have the same physical size and could be cast to one another with no loss, they would be interpreted differently by the compiler, correct?
|
|
|
|
« Last Edit: June 05, 2012, 05:33:06 pm by wanderson »
|
Logged
|
|
|
|
|
Offline
Full Member
Karma: 0
Posts: 100
|
 |
« Reply #18 on: June 05, 2012, 06:33:27 pm » |
On an ARM, yes. On an AVR, they would be different sizes. If you wanted to hold something like an IP address (32bits for v4), you could use an "int" on an ARM, but you'd have to use a "long" on an AVR: an incompatibility. Instead, your program should use "uint32_t" for the IP address, and it would run on both AVR and ARM (assuming all other architectural dependencies are fixed as well. Thats clear thanks "typedef" defines a name that acts like a type (ie like "int" or "long"); it's a shorthand convenience, especially when you get to more complex structures (containing other structures, etc.)
So someplace in an AVR include file there is likely to be a line that looks like: typedef unsigned long uint32_t; that means "treat the name "uint32_t" as a variable type, that is the same as "unsigned long". The similar file on an ARM might contain "typedef unsigned int uint32_t;" Not so clear! Its the code that confuses me Heres the form for the STM32F4, the name appears after the closing } // In a header file// typedef struct { Hours_Spent; Hairs_Pulled_Out;
}Learning_CTypeDef; //Capital T
Learning_CTypeDef Resinators_Learning_C;
Resinators_Learning_C.Hours_Spent = 999; Resinators_Learning_C.Hairs_Pulled_Out = LOTS;
Learning_CTypeDef Resinators_Learning_C; This makes a structure called Resinators_Learning_C which identical to the Learning_C Resinators_Learning_C.Hours_Spent = 999; Resinators_Learning_C.Hairs_Pulled_Out = LOTS; This populates the structure with the values What I dont get is the typedef it appears twice once at start with no capital and at the end where I name the structure
|
|
|
|
|
Logged
|
|
|
|
|
Dallas, Texas
Offline
God Member
Karma: 1
Posts: 689
Old, decrepit curmugeon
|
 |
« Reply #19 on: June 05, 2012, 07:04:25 pm » |
Where it appears at the end with the Capital the word Typedef is being used as part of the name used to indicate that particular structure. For instance it could have been created like so, and would still perform the same function typedef struct { Hours_Spent; Hairs_Pulled_Out;
} ArbitraryName; //Capital T
ArbitraryName Resinators_Learning_C;
Resinators_Learning_C.Hours_Spent = 999; Resinators_Learning_C.Hairs_Pulled_Out = LOTS;
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Full Member
Karma: 0
Posts: 100
|
 |
« Reply #20 on: June 06, 2012, 06:58:56 am » |
Thanks its really clear, the Typedef was just there in the name to remind me its a structure But what if it wasnt a structure and it was an enum?.... then what is the difference? typedef enum { Hours_Spent; Hairs_Pulled_Out;
} ArbitraryName;
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Full Member
Karma: 0
Posts: 100
|
 |
« Reply #21 on: June 06, 2012, 07:07:44 am » |
Also sometimes they dont put the name after the structure Usually looks like typedef struct{ Hours_Spent; Hairs_Pulled_Out;
} ArbitraryName; Sometimes typedef struct ArbitraryName{ Hours_Spent; Hairs_Pulled_Out;
} The difference is???
|
|
|
|
|
Logged
|
|
|
|
|
Dallas, Texas
Offline
God Member
Karma: 1
Posts: 689
Old, decrepit curmugeon
|
 |
« Reply #22 on: June 06, 2012, 08:18:35 am » |
|
|
|
|
|
Logged
|
|
|
|
|
SF Bay Area (USA)
Offline
Faraday Member
Karma: 78
Posts: 5454
Strongly opinionated, but not official!
|
 |
« Reply #23 on: June 06, 2012, 03:52:16 pm » |
typedef struct ArbitraryName{ Hours_Spent; Hairs_Pulled_Out; } No semicolon; perhaps the defined type name is on a subsequent line. Without a name, gcc gives me a warning: "foo.c:3: warning: useless storage class specifier in empty declaration" (It still defines "struct ArbitraryName"...)
|
|
|
|
|
Logged
|
|
|
|
|
Anaheim CA.
Offline
Edison Member
Karma: 31
Posts: 2309
Experienced old Whitebeard with a Full head of Hair...
|
 |
« Reply #24 on: June 06, 2012, 05:48:15 pm » |
Wow what a Bunch of GOOD STUFF!. I own an STM32 Eval kit (bought it for $14.+ from Newark at the same time I paid for my Raspberry Pi) and frankly it scared the Hell out of me. I am comfortable with ANY phase of electronics but know perhaps enough to engrave legibly on the head of a small pin, my total knowledge of 'C' and reading this thread has caused me to want to re-evaluate that board... Just as soon as I can find time... or a roundtoit... either one will work just fine... IMO...
Doc
|
|
|
|
|
Logged
|
“The solution of every problem is another problem.” -Johann Wolfgang von Goethe
|
|
|
|
Tacoma, WA
Offline
Full Member
Karma: 3
Posts: 179
Arduino rocks
|
 |
« Reply #25 on: June 06, 2012, 09:34:25 pm » |
It's a shame it's not as simple as simply adapting the Arduino environment/compiler to work on the STM32 boards.. I got the F4 back when it was free, and recently scored an F0 freebie as well.
|
|
|
|
|
Logged
|
Brian from Tacoma, WA Arduino evangelist - since Dec, 2010.
|
|
|
|
Offline
Full Member
Karma: 0
Posts: 100
|
 |
« Reply #26 on: June 07, 2012, 12:30:30 am » |
Wanderson great links thanks typedef struct ArbitraryName{ Hours_Spent; Hairs_Pulled_Out; } No semicolon; perhaps the defined type name is on a subsequent line. Without a name, gcc gives me a warning: "foo.c:3: warning: useless storage class specifier in empty declaration" (It still defines "struct ArbitraryName"...) Sorry mate, that code doesn't make sense I must of made a mistake when I copied it! Wow what a Bunch of GOOD STUFF!. I own an STM32 Eval kit (bought it for $14.+ from Newark at the same time I paid for my Raspberry Pi) and frankly it scared the Hell out of me. I am comfortable with ANY phase of electronics but know perhaps enough to engrave legibly on the head of a small pin, my total knowledge of 'C' and reading this thread has caused me to want to re-evaluate that board... Just as soon as I can find time... or a roundtoit... either one will work just fine... IMO...
Doc
The board is an amazing piece of kit, I am not very good with the C language myself but I know far more than I did two weeks ago just think how much I could know in two months! It's a shame it's not as simple as simply adapting the Arduino environment/compiler to work on the STM32 boards.. I got the F4 back when it was free, and recently scored an F0 freebie as well.
Its in no way as simple as the Arduino IDE and will never be, however the added complexity offers many advantages to whats possible Its actually not that bad if I can do it anyone can, get Attolic and it has a good embedded C project template it takes a couple of days to get familiar with that I will write a template program tonight if anyones interested, just a simple blinky program and by using the STLink debugger we can single step through and really see what happens, in essence its just a load of 1 and 0's that need to be written to certain registers I personally love the stm32f4
|
|
|
|
|
Logged
|
|
|
|
|
Tacoma, WA
Offline
Full Member
Karma: 3
Posts: 179
Arduino rocks
|
 |
« Reply #27 on: June 08, 2012, 04:18:44 pm » |
I disagree that it'll NEVER be as easy as the Arduino. The Maple Leaf board uses an Arduino style IDE, and is exactly like the Arduino when programming it. The Maple uses an STM32F1 if I'm not mistaken. As for an example sketch.. I'd like to see at least one of the ADC's get read, and then use that information to drive a PWM output. Maybe a stepper motor and i2c example too. At $8-$15 for a STM32 board, it'd make an extremely nice RepRap brain. Overkill, for sure, but for the price...
|
|
|
|
|
Logged
|
Brian from Tacoma, WA Arduino evangelist - since Dec, 2010.
|
|
|
|
Offline
Full Member
Karma: 0
Posts: 100
|
 |
« Reply #28 on: June 10, 2012, 07:32:42 am » |
I disagree that I agree to disagree!, its pretty head busting stuff I have managed some success, I actually feel like I am getting somewhere, it was pretty straightforward getting one ADC to work but I have struggled getting two to work separately its all this channel stuff that confuses me. I have a program that uses an interrupt to blink the orange LED and measures the input on Port C pin 0 (Channel 10) #include "stm32f4_discovery.h" #include <stdio.h> #include <math.h> #include "stm32f4xx.h" void INTTIM_Config(void); void IO_Config(void);
void ADC1_CH10_Config(void);
void TIM2_IRQHandler(void)//interrupt toggles orange LED = PD13 { if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) { GPIO_ToggleBits(GPIOD, GPIO_Pin_13);
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
} }
int main(void){
int *ADC1_DATA =0x4001204c;//ADC1 Data register (pointer to!)
INTTIM_Config(); IO_Config(); GPIO_SetBits(GPIOD, GPIO_Pin_15|GPIO_Pin_14|GPIO_Pin_12);//Set 3 LED's HIGH
ADC1_CH10_Config();
/* Enable ADC1 */ ADC_Cmd(ADC1, ENABLE);
/* Start ADC1 Software Conversion */ ADC_SoftwareStartConv(ADC1);
while (1) {
ADC_SoftwareStartConv(ADC1); float VIN = *ADC1_DATA*0.720214843 +16.0; float IIN = (VIN-2500.0)*0.745614035;
} }
void INTTIM_Config(void) { NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure);
/* TIM2 clock enable */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); /* Time base configuration */ TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_TimeBaseStructure.TIM_Period = 500000; // period 500000 = 0.5 seconds TIM_TimeBaseStructure.TIM_Prescaler = 80; // Prescale 80 = 1us per click TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); /* TIM IT enable */ TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); /* TIM2 enable counter */ TIM_Cmd(TIM2, ENABLE); }
void IO_Config(void)
{ /* GPIOD enable as output for LED's */ GPIO_InitTypeDef GPIO_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13| GPIO_Pin_14| GPIO_Pin_15; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOD, &GPIO_InitStructure);
/* GPIOC enable as analog input */ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1 ; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; GPIO_Init(GPIOC, &GPIO_InitStructure);
} /* ENABLE ADC1 (channel 10=PC0) */ void ADC1_CH10_Config(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); ADC_CommonInitTypeDef ADC_CommonInitStructure; ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent; ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2; ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles; ADC_CommonInit(&ADC_CommonInitStructure);
ADC_InitTypeDef ADC_InitStructure;
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b; ADC_InitStructure.ADC_ScanConvMode = DISABLE; ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; ADC_InitStructure.ADC_ExternalTrigConv=ADC_ExternalTrigConv_T1_CC1; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfConversion = 1; ADC_Init(ADC1, &ADC_InitStructure);
/* ADC1 regular channels 10 configuration */ ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_56Cycles);
}
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Full Member
Karma: 0
Posts: 100
|
 |
« Reply #29 on: June 10, 2012, 02:36:39 pm » |
I have had some good success today, I have managed to get three ADC's working independently However I am unable to configure a single port to work with a single ADC, for example if I use port A pin 0 for ADC1 then trying to configure port A pin 1 to another ADC doesn't work???, so I have had to use a port per an ADC ADC1=PortA ADC2=PortB ADC3=PortC I wish I knew how to just use one ADC and a single port but it seems like I would have to reconfigure all over again which I would rather just use another ADC after all it is available I should of mentioned above the reference voltage is 2.96V I dont know how to change this as I have read upto 3.6V as a reference I tried tying VDD to 3.6V but nothing changes Heres three setup functions that can be called to setup GPIO and the three ADC's void IO_Config(void)
{ /* GPIOD Periph clock enable */ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13| GPIO_Pin_14| GPIO_Pin_15; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOD, &GPIO_InitStructure);
GPIO_InitTypeDef GPIO_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 ; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; GPIO_Init(GPIOC, &GPIO_InitStructure);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 ; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; GPIO_Init(GPIOB, &GPIO_InitStructure);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 ; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; GPIO_Init(GPIOA, &GPIO_InitStructure); }
void ADC1_PA0_CH0_Config(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); ADC_CommonInitTypeDef ADC_CommonInitStructure; ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent; ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2; ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles; ADC_CommonInit(&ADC_CommonInitStructure);
ADC_InitTypeDef ADC_InitStructure;
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b; ADC_InitStructure.ADC_ScanConvMode = DISABLE; ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; ADC_InitStructure.ADC_ExternalTrigConv=ADC_ExternalTrigConv_T1_CC1; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfConversion = 1; ADC_Init(ADC1, &ADC_InitStructure);
/* ADC1 regular channels 10 configuration */ ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_56Cycles); /* Enable ADC1 */ ADC_Cmd(ADC1, ENABLE); }
void ADC2_PB0_CH8_Config(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC2, ENABLE); ADC_CommonInitTypeDef ADC_CommonInitStructure; ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent; ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2; ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles; ADC_CommonInit(&ADC_CommonInitStructure);
ADC_InitTypeDef ADC_InitStructure;
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b; ADC_InitStructure.ADC_ScanConvMode = DISABLE; ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; ADC_InitStructure.ADC_ExternalTrigConv=ADC_ExternalTrigConv_T1_CC1; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfConversion = 1; ADC_Init(ADC2, &ADC_InitStructure);
ADC_RegularChannelConfig(ADC2, ADC_Channel_8, 1, ADC_SampleTime_56Cycles); /* Enable ADC2 */ ADC_Cmd(ADC2, ENABLE); }
void ADC3_PC0_CH10_Config(void) {RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE); ADC_InitTypeDef ADC_InitStructure; ADC_CommonInitTypeDef ADC_CommonInitStructure; ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent; ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2; ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles; ADC_CommonInit(&ADC_CommonInitStructure);
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b; ADC_InitStructure.ADC_ScanConvMode = DISABLE; ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfConversion = 1; ADC_Init(ADC3, &ADC_InitStructure);
ADC_RegularChannelConfig(ADC3, ADC_Channel_10, 1, ADC_SampleTime_56Cycles); /* Enable ADC3 */ ADC_Cmd(ADC3, ENABLE);
}
|
|
|
|
« Last Edit: June 10, 2012, 02:52:29 pm by Resinator »
|
Logged
|
|
|
|
|
|