[소개]
마이크로 컨트롤러 기술은 현대 산업 자동화, 전자, 전기 공학 및 사물 인터넷(IoT)에서 없어서는 안 될 주류 기술입니다. 우리 삶이 점점 스마트해지면서 마이크로컨트롤러 기술은 스마트 밥솥, 스마트 스피커 등 우리 일상생활의 거의 모든 면에 스며들었습니다.
이를 염두에 두고 "51 마이크로컨트롤러 다시 배우기" 기사 시리즈는 초보자가 마이크로컨트롤러 기술을 시작하는 데 도움을 주는 것을 목표로 합니다. 가장 간단한 작업인 -단일 LED 켜기-부터 시작해 버튼 컨트롤, LCD1602 디스플레이, DS18B20 및 DS1302 온도 센서, 두 마이크로컨트롤러 간 통신과 같은 모듈 구현으로 점진적으로 진행하겠습니다. 또한 UART, I²C 및 SPI와 같은 하드웨어 통신 프로토콜도 다룹니다. 이러한 개념을 C 프로그래밍 기술과 결합함으로써 실제 엔지니어링 프로젝트를 사용하여 프로그래밍 접근 방식을 설명하고 C 포인터와 구조를 유연하게 적용하여 모듈식 프로그래밍을 달성할 수 있습니다.
이제 주요 주제로 돌아가 보겠습니다. 51 마이크로컨트롤러를 사용하여 LED를 제어하고 숨쉬는 조명 효과를 생성합니다.
[호흡등의 작동 원리]
먼저 호흡 조명 효과가 어떻게 작동하는지 살펴보겠습니다.
호흡하는 빛은 점차 밝아졌다가 점차 어두워지며, 호흡과 유사한 방식으로 이 주기를 반복합니다. 그러나 마이크로 컨트롤러의 핀은 1(켜짐) 또는 0(꺼짐)만 출력할 수 있으므로 점진적인 전환 효과를 어떻게 얻을 수 있습니까?
이는 우리 눈의 시력이 지속되기 때문입니다. 우리가 무언가를 볼 때 우리 눈에 형성된 이미지는 0.04초 동안 지속됩니다(이 수치는 온라인에서 찾았습니다).
0.04초를 기준으로 계산하면 40ms가 됩니다. 따라서 LED가 각각 20ms 동안 켜지고 꺼지면 사람의 눈에는 계속 켜져 있는 것처럼 보입니다.

LED가 20ms 동안 켜지고 20ms 동안 꺼지는 효과는 항상 켜져 있는 것과 동일합니까?
하하, 확실히 다릅니다. 조명이 20밀리초마다 켜졌다 꺼졌다를 반복할 때 우리가 보는 효과는 계속 켜져 있을 때보다 더 어두워집니다. 계속 켜져 있는 조명의 밝기를 100%라고 가정하면 20밀리초마다 켜졌다 꺼졌다를 반복하는 조명의 밝기는 50%입니다. 이를 바탕으로 LED의 밝기를 조정할 수 있습니다.

이 시점에서 우리는 LED의 밝기를 조정할 수 있습니다(40ms 주기 내에서 하이 레벨의 지속 시간을 설정하여). 이것이 잘 알려진 밝기 제어의-PWM(Pulse Width Modulation) 방법의 원리이며, 높은 레벨의 지속 시간을 설정하는 것은 듀티 사이클(즉, 높은 레벨의 지속 시간을 전체 주기로 나눈 값: 20/40=50%)을 조정하는 것과 동일합니다.
여기서 가장 중요한 요소는 바로 이 Duty Cycle입니다. 예를 들어, 주기가 20ms이고 LED가 10ms 켜짐과 10ms 꺼짐 사이를 번갈아 가며 인식되는 밝기는 여전히 50%입니다(즉, 듀티 사이클은 10/20=50%).
다음으로 이것이 프로그램에서 어떻게 구현되는지 살펴보겠습니다.
[프로그램 구현]
LED 켜기
먼저 LED를 켜는 것부터 시작해 점차 호흡하는 조명 효과를 구현해 보겠습니다. 우리가 사용할 하드웨어는 다음과 같습니다.
| 개발 보드 | ZeroOne 마이크로컨트롤러 교육 개발 보드 |
|---|---|
| 마이크로컨트롤러 모델 | STC89C52 |
| LED 인터페이스 | 핀 P4^4 |

회로도에서 LED가 마이크로컨트롤러의 P4^4 핀에 연결되어 있음을 알 수 있습니다. 마이크로 컨트롤러가 1을 출력하면 LED가 켜집니다. 0을 출력하면 LED가 꺼집니다. 따라서 LED를 켜는 프로그램은 아래와 같이 매우 간단합니다.

LED를 켜는 프로그램은 매우 간단합니다. 나는 모두가 그것을하는 방법을 알고 있다고 확신합니다.
LED 밝기 조정
다음으로, 다음과 같이 밝기를 조정(즉, 듀티 사이클 조정)할 수 있는 기능을 구현하겠습니다.

듀티 사이클을 저장하기 위해 정적 변수 'duty_cycle'을 정의합니다. 'flag'가 1이면 듀티 사이클은 255까지 점진적으로 증가한 다음 'flag'를 0으로 설정하고 'duty_cycle'은 255에서 0으로 점차 감소합니다. 이 사이클을 반복합니다.
하하, 이쯤 되면 호흡등이 이미 작동하고 있다고 생각하실 수도 있겠지만, 그렇지 않습니다. 내 말을 믿을 수 없다면 위의 코드를 직접 시도해 보세요.
그렇다면 문제는 정확히 어디에 있습니까?
문제는 밝기-설정 함수 `set_led_luminance()`를 직접 호출하는 데 있습니다. 이 기능은 한 사이클을 완료하는 데 40ms가 걸립니다. 즉, 해당 40ms 동안 듀티 사이클을 변경할 수 없습니다. 그렇지 않으면 밝기 조정이 작동하지 않습니다. 'breath_led' 함수를 다시 살펴보겠습니다. 듀티 사이클을 설정하기 위해 'set_led_luminance()'를 호출할 때마다 40ms를 기다리지 않고 즉시 'duty_cycle' 값을 변경합니다.
이 시점에서 40ms가 경과한 후 `duty_cycle` 값을 업데이트하기 위해 소프트웨어 타이머를 추가해야 합니다. 수정된 프로그램은 다음과 같습니다.

참고: 타이머 지속 시간은 40ms보다 커야 하지만(즉 `s_breathCounter` 값이 255보다 커야 함) 주기의 배수로 설정하는 것이 가장 좋습니다. 예를 들어, 주기가 255(즉, 0부터 255까지의 256개 값)인 경우 해당 값의 두 배인 256 * 2 - 1=511(즉, 0부터 511까지의 512개 값)으로 설정할 수 있습니다.
그리고 여기까지 왔습니다.-우리의 호흡하는 빛이 완성되었습니다! 간단하지 않나요? (* ̄︶ ̄)
다음은 오늘의 보너스 섹션입니다.
숨쉬는 조명 효과를 달성했지만 코드가 충분히 간결하거나 우아하지 않습니다.-많은 if 및 else 문을 사용합니다. 좀 더 단순화할 수 있는지 살펴보겠습니다.
먼저 아래 그림과 같이 set_led_luminance() 함수의 이 섹션을 단순화해 보겠습니다.

이를 단순화하기 전에 C: 비트 AND 연산에 대한 간단한 팁을 살펴보겠습니다.

이를 통해 우리는 1인지 0인지 0으로 비트 AND 연산을 수행하면 0이 된다는 것을 알 수 있습니다.
1이든 0이든 1로 비트 AND 연산을 수행하면 원래 값이 됩니다.
편의상 16진수 표기법(접두사 "0x")을 사용합니다. 예를 들어 0xff는 10진수 255에 해당합니다. 그러므로,
0xff보다 작거나 같은 숫자를 0xff와 AND로 처리하면 결과는 아래와 같이 숫자 자체가 됩니다.

0xff보다 큰 숫자와 0xff 사이에 비트 단위 AND 연산을 수행하면 어떻게 되나요?

결과는 이 숫자를 (0xff + 1)로 나눈 나머지입니다(즉, 결과는 여전히 0과 0xff 사이에 있습니다).
이 비트별 AND 연산을 사용하면 위의 코드를 다음과 같이 단순화할 수 있습니다.

이렇게 하면 s_Counter의 값은 항상 0x00에서 0xff 범위 내에 있게 됩니다.
마찬가지로 위의 Breath_led 함수의 소프트웨어 타이머도 다음과 같이 단순화할 수 있습니다.

3번째 줄에서 0x1ff는 10진수로 511입니다. s_breathCounter의 값이 (0x1ff+1) 또는 512일 때 조건은 true입니다. 왜냐하면 512 & 0x1ff=0. 앞에 있는 느낌표는 비트별 NOT 연산을 나타냅니다(정확하게 말하면 `s_breathCounter`의 값이 512의 배수일 때 조건이 충족됩니다. 이렇게 하면 `s_breathCounter`를 재설정할 필요가 없어집니다. 이 설명이 다음과 같기를 바랍니다. 명확합니다-잘 생각해 보세요). 조건이 충족되면 듀티 사이클이 증가하거나 감소하기 시작합니다.
그런데 듀티 사이클 범위가 0~255 아닌가요? 5행도 0x1ff(511)가 되는 이유는 무엇입니까? 걱정하지 마세요-8행을 보세요. 0xff를 다시 빼므로 듀티 사이클 범위는 0~255로 유지됩니다.
7~10행의 의미: 'duty_cycle > (0xff)', 즉 256~511인 경우 0xff를 빼는 것은 1에서 255로 증가하는 것과 같으므로 밝기가 점차 증가합니다.
듀티사이클일 때<= 0xff, the duty_cycle increases from 0 to 255, while the set brightness is 255 - duty_cycle. This effectively decreases the brightness from 255 to 0, causing the light to gradually dim. This achieves the breathing light effect.
하하, 우리 단순화가 끝났다고 생각하셨나요?
아니, 아니, 아니
실제로 7~10행은 훨씬 더 단순화될 수 있습니다. 여기서 절대값 함수가 유용하게 사용됩니다.
무엇? 절대값 함수를 사용하는 이유는 무엇입니까?
10행을 보십시오. 0xff - Duty_cycle은 Duty_cycle - 0xff와 동일하며 절대값을 취합니다. 좋습니다. 단순화된 코드는 다음과 같습니다.
절대값을 구하는 매크로 함수는 다음과 같습니다.
마지막으로 아래에 전체 단순화된 코드를 포함했습니다.

어떻게 생각하나요? 간단하지 않나요? (* ̄︶ ̄)




