- mcu는 c에 최적화되어 있다. (안전등급 충족 X)
조건문
- if문에서 왼쪽 식이 만족하지 않으므로, y++은 실행되지 않는다.
#include <stdio.h>
int main() {
int x = 5; int y = 10;
if (x < 0 && y++ == 15){
printf("이 코드는 실행되지 않습니다.\n");
}
printf("y = %d\n", y); // y = 10
}
형변환
#include <stdio.h>
#include <stdlib.h>
int main() {
// %u: unsigned_int
char s8_1 = 0, s8_2 = 0;
short s16_1 = 32767;
int s32_1 = -1;
unsigned int u32_1 = 1u;
printf("1. %d\n", sizeof(s8_1 + s8_2));
printf("2. %d, %d, %u\n", sizeof(32767 * 100000), 32767 * 100000, 32767 * 100000);
printf("3. %d, %u\n", -1, -1);
if (s32_1 < u32_1) { // unsigned로 형변환 된다.
printf("4. s32_1 < u32_1 is true\n");
}
else {
printf("4. s32_1 < u32_1 is false\n");
}
system("pause");
return 0;
}
* 자료형 처리 속도: char < int < long < float < double
* 명시적 형변환을 권장함.
원하는 자료형이 char 타입보다 크기가 작아서
shift 연산
(연습1)
1. SWE_EN = Enable
2. BR_RATIO = Ratio <= 4
3. BR = 500kbp/s
위와 같이 registerValue 값을 바꿔보자.
#include <stdio.h>
#include <stdlib.h>
int main()
{
unsigned char registerValue = 0;
registerValue |= (1<<7);
registerValue |= (1<<2);
for (int i = 7; i >= 0; i--) {
printf("%d", (registerValue & (1 << i)) ? 1 : 0);
}
printf("\n"); // 10000100
return 0;
}
(연습2)
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
int main()
{
uint8_t flags = 0;
// 0 번째 Bit 부터 Fail_0 ~ 7 이다.
// 0,2,3,5,7 번째 Fail 이 발생했을 때 이를 입력하라
flags |= (1 << 0); // Fail_0
flags |= (1 << 2); // Fail_2
flags |= (1 << 3); // Fail_3
flags |= (1 << 5); // Fail_5
flags |= (1 << 7); // Fail_7
// Fail_0부터 Fail_7까지 값을 검색하고 출력합니다.
for (int i = 0; i < 8; i++) {
uint8_t flag = (flags & (1 << i)) ? 1 : 0;
printf("Fail_%d: %d\n", i, flag);
}
}
(연습3)
각 Can Bit별 Parsing하는 code를 작성하라
#include <stdio.h>
#include <stdint.h>
int main() {
//Current Data : 164,32,0,4 G Sensor : 32,38,4,a
uint8_t canDataArray[8] = { 0x64, 0xC9, 0x00, 0x00, 0x01, 0x32, 0x4E, 0x28 };
// 10비트 단위로 추출된 데이터
uint16_t currentData1, currentData2, currentData3, currentData4;
currentData1 = (canDataArray[0]) | (((uint16_t)canDataArray[1] & 0x03) << 8);
currentData2 = (canDataArray[1] >> 2) | (((uint16_t)canDataArray[2] & 0x0F) << 6);
currentData3 = (canDataArray[2] >> 4) | (((uint16_t)canDataArray[3] & 0x3F) << 4);
currentData4 = (canDataArray[3] >> 6) | (((uint16_t)canDataArray[4] << 2));
// 6비트 단위로 추출된 데이터
uint8_t gsensor1, gsensor2, gsensor3, gsensor4;
gsensor1 = canDataArray[5] & 0x3F;
gsensor2 = (canDataArray[5] >> 6) | ((canDataArray[6] & 0x0F) << 2);
gsensor3 = (canDataArray[6] >> 4) | ((canDataArray[6] & 0x03) << 4);
gsensor4 = (canDataArray[7] >> 2);
printf("Current Data:\n");
printf("Current 1: %x\n", currentData1);
printf("Current 2: %x\n", currentData2);
printf("Current 3: %x\n", currentData3);
printf("Current 4: %x\n", currentData4);
printf("\nGsensor Data:\n");
printf("Gsensor 1: %x\n", gsensor1);
printf("Gsensor 2: %x\n", gsensor2);
printf("Gsensor 3: %x\n", gsensor3);
printf("Gsensor 4: %x\n", gsensor4);
return 0;
}
- OR 연산(|)은 같은 위치의 비트 중 하나라도 1이면 1을 반환
- AND 연산(&)은 같은 위치의 비트가 모두 1일때만 1 반환
- 0x03의 2진수 표현은 0000 0011 -> and 연산하여, 하위 2비트를 추출
- 0x0F의 2진수 표현은 0000 1111 -> and 연산하여, 하위 4비트를 추출
- 0x3F의 2진수 표현은 0011 1111 -> and 연산하여, 하위 6비트를 추출
Little Endian, Big Endian
: 데이터를 메모리에 저장하거나 전송할 때 바이트의 순서를 정의하는 방법
Little Endian(인텔)
- 가장 작은 의미의 바이트(LSB)를 가장 낮은 주소에 저장.
- 큰 의미의 바이트(MSB)는 더 높은 주소에 저장.
예제 (32비트 데이터: 0x12345678):
메모리 주소: [0] [1] [2] [3]
저장 값: 0x78 0x56 0x34 0x12
특징
- Intel x86 계열 CPU가 Little Endian을 사용.
- 하드웨어에서 낮은 주소부터 읽을 때 효율적.
Big Endian(모토로라)
- 최상위 바이트(Most Significant Byte, MSB)가 가장 낮은 메모리 주소에 저장.
- 하위 바이트(LSB)는 더 높은 주소에 저장.
예제 (32비트 데이터: 0x12345678):
메모리 주소: [0] [1] [2] [3]
저장 값: 0x12 0x34 0x56 0x78
특징
- 네트워크 프로토콜(TCP/IP)은 Big Endian을 사용 (네트워크 바이트 순서).
- 사람이 숫자를 읽는 방식과 유사하여 이해하기 쉬움.
'IVS > C 프로그래밍' 카테고리의 다른 글
[C] const 키워드 (0) | 2025.01.13 |
---|---|
[C/C++] 배열 초기화 - memset, fill (0) | 2025.01.13 |
[C++] 문자열 처리- strcmp, strcpy, strcat (0) | 2025.01.09 |
[C++] 공백있는 문자열 입력받기 - getline (2) | 2025.01.09 |
[C++] 중첩 반복문 - continue, break (0) | 2025.01.08 |