임베디드/ARM Cortex-M42015. 7. 10. 19:59

DAC

ADC완 반대로 디지털신호를 아날로그신호로 변환시키는 것으로

마이크로프로세서 내부에서 처리된 값으로 엑츄에이터(Actuator)를 동작시킬 때 사용될 수 있다.

예를 들어 LED의 밝기를 조절하고 하고자 할 때 LED로 들어가는 전압의 세기를 변화시켜야 할 것이다.

이 때 DAC가 사용될 수 있다.

 

DAC 초기화 소스

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
void Init_DAC(){
 
        GPIO_InitTypeDef GPIO_InitStructure;
 
        DAC_InitTypeDef DAC_InitStructure;
 
 
 
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
 
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);
 
 
 
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;
 
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
 
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
 
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
 
 
 
        GPIO_Init(GPIOA, &GPIO_InitStructure);
 
 
 
        DAC_InitStructure.DAC_Trigger = DAC_Trigger_None;
 
        DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
 
        DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable;
 
        DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = DAC_TriangleAmplitude_4095;
 
        DAC_Init(DAC_Channel_1, &DAC_InitStructure);
 
 
 
        DAC_SetChannel1Data(DAC_Align_12b_R, 0);
 
        DAC_Cmd(DAC_Channel_1, ENABLE);
 
}
 
cs

 DAC는 PA4,5로 사용이 가능하다.

 

어떻게 쓰는가?

1
DAC_SetChannel1Data(DAC_Align_12b_R, 변수);
cs

위와 같은 코드를 사용하면 A포트를 통해서 '변수'의 값이 전압의 형태로 출력된다.

Posted by gharlic
임베디드/ARM Cortex-M42015. 7. 10. 19:51

ADC(Analog-Digital Converter)란

 아날로그 신호를 디지털 신호로 변환시켜주는 것이다.

아날로그 신호란 자연계에서의 수치로 음성, 온도, 압력의 세기 따위를 전압의 세기로 나타내는 것이다.

디지털 신호, 다른 말로 디스크리트(discrete) 신호는 High와 Low로 구분되는 이산적인 값이다.

 

어디에 쓰나?

 마이크로프로세서에서 ADC는 외부 센서(온도 센서, 적외선 센서, 초음파 센서, 가속도 등)으로 부터

읽어들인 아날로그 값을 처리하기 위해 디지털 신호로 변환시키는데 사용된다.

측정값이 전압의 세기로 나타내지는 센서들은 모두 ADC를 거쳐야한다고 생각하면 된다.

 

ADC 초기화 소스

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
void Init_ADC(){
 
        GPIO_InitTypeDef GPIO_InitStructure;
 
        ADC_InitTypeDef ADC_InitStructure;
 
        ADC_CommonInitTypeDef ADC_CommonInitStructure;
 
 
 
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
 
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
 
 
 
        ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
 
        ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;
 
        ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
 
        ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
 
        ADC_CommonInit(&ADC_CommonInitStructure);
 
 
 
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
 
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
 
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
 
        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
 
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 
        GPIO_Init(GPIOC, &GPIO_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);
 
        ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_3Cycles);
 
        ADC_Cmd(ADC1, ENABLE);
 
}
 
cs

 이전 게시물에서 밝혔듯이 대부분의 기능은 GPIO가 겸하고 있기 때문에 ADC뿐만 아니라 GPIO도 설정해야한다.

http://gharlic.tistory.com/2 게시물을 참고하자. ADC는 PC0,2,3에 배치되어있다.

위 초기화코드는 PC0로 아날로그입력을 받겠다고 설정하는 부분이다.

분해능을 12bit로 잡았으므로 0 ~ (2^12)-1의 범위의 값이 읽어들여질 것이다.

초기화함수를 작성했으면 main함수에서 초기화함수를 실행시키는 것은 기본이다.

 

읽어온 값은 어디로?

1
2
3
4
5
6
7
ADC_SoftwareStartConv(ADC1);
 
 
 
if (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == SET)
 
         x = ADC_GetConversionValue(ADC1);
cs

 타이머 핸들러에 위의 코드를 작성하면 x변수로 정수형값을 확인할 수 있다.


Posted by gharlic

 GPIO(General Purpose Input Output)은 쉽게 말해 다용도 입출력 기능으로

GPIO는 입출력 뿐만 아니라 후에 다루게될 ADC, DAC를 포함해서 Timer까지 등까지 대부분의 기능을 겸한다.

GPIO를 통해 외부에서 swt등으로 입력하는 신호를 입력받을 수 도 있고

MCU내부에서 처리한 값을 GPIO를 통해 LED등의 소자로 출력할 수 도 있다.

 

다음은 OUT모드로 GPIO를 초기화시키는 소스이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void Init_GPIO() {
 
        GPIO_InitTypeDef GPIO;
 
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);
 
        GPIO.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4;
 
        GPIO.GPIO_Mode = GPIO_Mode_OUT;
 
        GPIO.GPIO_PuPd = GPIO_PuPd_NOPULL;
 
        GPIO.GPIO_OType = GPIO_OType_PP;
 
        GPIO.GPIO_Speed = GPIO_Speed_100MHz;
 
        GPIO_Init(GPIOE, &GPIO);
 
}
 
cs

GPIO E포트의 1,2,3,4번 핀을 OUT모드로 설정한다.

 

1
2
3
4
GPIO_SetBits(GPIOE,GPIO_Pin_01);
 
GPIO_ResetBits(GPIOE,GPIO_Pin_01);
 
cs

다음과 같은 소스로 E포트 1번핀을 Set/Reset시킬 수 있다.

 

 

다음은 IN모드로 GPIO를 초기화시키는 소스이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void Init_GPIO() {
 
        GPIO_InitTypeDef GPIO;
 
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);
 
        GPIO.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4;
 
        GPIO.GPIO_Mode = GPIO_Mode_IN;
 
        GPIO.GPIO_PuPd = GPIO_PuPd_NOPULL;
 
        GPIO.GPIO_OType = GPIO_OType_PP;
 
        GPIO.GPIO_Speed = GPIO_Speed_100MHz;
 
        GPIO_Init(GPIOE, &GPIO);
 
}
 
cs

GPIO E포트의 1,2,3,4번 핀을 IN모드로 설정한다.

 

1
int a = GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_1);
cs

다음과 같은 소스로 변수 a에 E포트 1번으로 입력된 값을 읽어들일 수 있다.

이 때 a의 값을 활용할 때에는 Low는 0, High는 1이 정확하게 나오지 않기 때문에

값을 비교할 땐 if ( a == 0 )이 참이면 Low

if ( a != 0 )이 참이면 High신호가 입력된 것으로 활용 하여야한다.

Posted by gharlic