내 연락처 정보
우편메소피아@프로톤메일.com
2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
다른 CSDN 블로거의 블로그 게시물(개인용) 임베디드 연구 노트 9-51 마이크로컨트롤러 UART 직렬 통신_51uart 직렬 통신-CSDN 블로그
다른 CSDN 블로거가 작성한 블로그 게시물은 매우 훌륭합니다. 51 마이크로 컨트롤러 UART 직렬 포트에 대해 알고 싶다면 클릭하여 살펴볼 수 있습니다.
비동기 통신통신에서 두 문자(8비트) 사이의 시간 간격은 고정되어 있지 않지만, 한 문자 내에서는 비트 사이의 시간 간격이 고정되어 있음을 의미합니다.안정적인。
UART 직렬 통신은 마이크로컨트롤러에 가장 일반적으로 사용되는 통신 기술로, 일반적으로 마이크로컨트롤러와 컴퓨터 간, 마이크로컨트롤러 간 통신에 사용됩니다.
의사소통은 기본 유형으로 나눌 수 있다병렬 통신그리고직렬 통신, 병렬 통신에서는 데이터의 각 비트가 동시에 전송되며, 통신은 바이트 단위로 구현될 수 있습니다. 그러나 여러 개의 통신 회선이 많은 자원을 차지하며 비용이 많이 듭니다. 예를 들어 이전에 사용된 P0 = 0xFF는 P0의 8개 IO 포트에 동시에 값을 할당하여 동시에 신호를 출력하는 방식으로, 8개의 차선이 동시에 통과할 수 있는 것과 유사합니다. 이 형식은 병렬입니다. 51 마이크로컨트롤러의 병렬 버스 4개 세트를 P0, P1, P2 및 P3이라고 부르는 것이 일반적입니다.
직렬 통신은 차선과 같아서 한 번에 한 대의 자동차만 지나갈 수 있습니다.0xFF와 같은 데이터 바이트를 전송하려면 자동차가 1비트 데이터를 가져온다고 가정하면 8대 이상의 자동차가 필요합니다.같은 시간 간격같은 차선을 순서대로 건너세요.
동기식 통신과 비동기식 통신의 차이점:
1. 동기 통신에서는 수신 측의 클록 주파수가 송신 측의 클록 주파수와 일치해야 하며 송신 측에서는 연속적인 비트 스트림을 전송해야 합니다. 비동기 통신에서는 수신 측 클록과 송신 측 클록의 동기화가 필요하지 않습니다. 송신 측에서 바이트를 보낸 후 다음 바이트를 보내기 전에 긴 시간 간격을 통과할 수 있습니다.
2. 동기식 통신은 효율성이 높고 비동기식 통신은 효율성이 낮습니다.
3. 동기식 통신은 더 복잡하며 양 당사자의 시계에 허용되는 오류는 적습니다. 비동기식 통신은 간단하며 양 당사자의 시계는 특정 오류를 허용할 수 있습니다.
4. 동기 통신은 지점 대 다중 지점에만 적합하며 비동기 통신은 지점 간 통신에 사용할 수 있습니다.
STC89C52 마이크로 컨트롤러에는 UART 직렬 통신에 특별히 사용되는 두 개의 핀이 있습니다. 하나는 P3^0이고 다른 하나는 P3^1입니다. 또한 각각 RXD(데이터 수신) 및 TXD(데이터 전송)라는 다른 이름으로 구성됩니다. 이를 직렬 인터페이스라고 합니다. 그림과 같이:
마이크로컨트롤러와 마이크로컨트롤러 간의 통신:
그림에서 GND는 마이크로 컨트롤러 시스템 전원 공급 장치의 기준 접지를 나타냅니다. TXD는 직렬 송신 핀, RXD는 직렬 수신 핀이라고 합니다.
두 마이크로컨트롤러 간에 통신하려면 먼저 전원 공급 장치 레퍼런스가 동일해야 하므로 두 마이크로컨트롤러의 GND가 서로 연결되어야 합니다.그런 다음 MCU 1의 TXD 핀을 MCU 2의 RXD 핀에 연결합니다. MCU 1이 MCU 2에 정보를 보내는 기능입니다. (이 프로세스는 두 부분으로 나뉩니다. MCU 1의신호를 보내다마이크로컨트롤러 2를 사용한 프로세스신호를 수신하다과정) 같은 방법으로 마이크로컨트롤러 2의 TXD 핀을 마이크로컨트롤러 1의 RXD 핀에 연결합니다.
이 개략도는 두 개의 마이크로컨트롤러가 서로 정보를 주고받는 과정을 반영합니다.
마이크로컨트롤러 1이 마이크로컨트롤러 2에 데이터를 보내려고 할 때(예: 이진 형식으로 표현되는 1 0xE4 데이터 전송):
0b1110 0100, 마이크로 컨트롤러 1은 전송이 시작되기 전에 몇 가지 문제에 직면합니다.
가장 낮은 비트인 0을 먼저 전송한 다음 마이크로컨트롤러 1의 TXD 포트를 낮은 레벨로 설정해야 한다고 가정합니다.
마이크로컨트롤러는 일반적으로 TTL 또는 CMOS 레벨입니다. TTL/CMOS 레벨 표준의 경우:
2.0V보다 큰 것은 높은 수준이고, 0.0V보다 작은 것은 낮은 수준이며, 그 사이의 모든 것은 높은 수준도 아니고 낮은 수준도 아닙니다. 그 사이의 논리는 혼란스러울 수 있으며 장치에 의해 판단될 수 있습니다. 높은 수준이면 낮은 수준으로 판단될 수도 있습니다. 따라서 이 영역에서는 회로를 작동하지 마십시오. 이 영역에 있으면 제품이 성공하거나 실패할 수 있습니다. 따라서 제품을 개발할 때에는 소자의 데이터시트와 회로 동작 시 전압을 확인하여 적절한 전압인지 확인해야 합니다.
1. TTL 수준:
출력 하이 레벨 >2.4V, 출력 로우 레벨 <0.4V. 실온에서 일반 출력 하이 레벨은 3.5V이고 출력 로우 레벨은 0.2V입니다. 최소 입력 하이 레벨 및 로우 레벨: 입력 하이 레벨 >=2.0V, 입력 로우 레벨 <=0.8V, 잡음 마진은 0.4V입니다.
2. CMOS 레벨:
1논리 레벨 전압은 공급 전압에 가깝고 0 로직 레벨은 0V에 가깝습니다. 그리고 소음에 대한 내성이 넓습니다.
그래서 여기에 질문이 옵니다:
정보가 전송되거나 수신되지 않는 경우 마이크로컨트롤러(1)의 전송 포트(TXD)는 하이 레벨 또는 로우 레벨이 되거나 포트의 전압이 이들 사이에 있게 됩니다. MCU 2의 수신 포트 전압(RXD)은 MCU 1의 전송 포트 전압을 따릅니다. MCU 1이 정보 전송을 시작하려고 한다는 신호를 설정하는 방법, 즉 MCU 2는 MCU 1이 정보를 전송했다는 것을 어떻게 알 수 있습니까? 따라서 통신표준을 표준화할 필요가 있다.
1단계: 통신이 발생하지 않을 때 마이크로 컨트롤러의 TXD 및 RXD 포트의 전압은 높게 유지되도록 규정되어 있습니다.
2단계: 아래와 같이 데이터 전송 방법을 표준화합니다.
1개의 시작 비트, 1개의 정지 비트, 전송할 데이터 1바이트를 더해 총 8비트를 정의하는 것을 볼 수 있습니다.10자리 데이터。
위에서 언급한 0xE4 데이터의 전송은 실제로 0 1110 0100 1을 전송합니다. MCU 1에서 MCU 2로 1바이트의 데이터가 실제로 전송되는 것은 이 10비트 전체를 완전한 직렬 데이터 프레임이라고 합니다.
시작 비트와 정지 비트를 사용하면 마이크로컨트롤러 2 RXD 포트가 낮은 레벨을 감지할 때 데이터 수신 준비를 시작합니다. 같은 방식으로 마이크로컨트롤러 1이 1바이트의 데이터를 전송하려면 먼저 시작 비트 0을 전송하고(마이크로컨트롤러 2에 수신 준비를 지시) 정지 비트 1을 전송해야 합니다(마이크로컨트롤러 2에게 바이트 수를 지시). 데이터 전송이 완료되었습니다).그리고 데이터를 전송할 때,처음에는 낮았다가 나중에 높음주문하다
3단계: 1비트의 데이터를 전송하는 데 필요한 시간을 균일하게 설정해야 합니다. 이 시간의 속도는 전송 속도(baud)로 표시됩니다. 보드율 1은 1초에 1비트의 데이터를 전송한다는 의미이고, 보드율 9600은 1초에 9600비트의 데이터를 전송한다는 의미입니다.
그런 다음 1비트를 전송한 결과를 얻습니다.지속 시간=1/보드., 1개의 완전한 데이터 프레임을 전송하는 데 걸리는 시간은 다음과 같다.10/보드,데이터 프레임 사이의 시간 간격은 임의적입니다.
MCU 1과 MCU 2가 신호를 전송할 때 올바른 통신을 위해서는 전송 속도를 일관되게 설정해야 합니다.
데스크탑 컴퓨터 초기에는 일반적으로 9핀 직렬 인터페이스가 있었는데, 이 직렬 인터페이스는 UART 통신과 관련된 RS-232 인터페이스라고 합니다. 그러나 최신 노트북에는 더 이상 이 9핀 직렬 인터페이스가 없습니다. 따라서 마이크로컨트롤러와의 통신에서는 USB 가상 직렬 포트를 사용하는 경향이 점점 더 커지고 있습니다.
RS232에서 사용되는 레벨 로직은 TTL/CMOS 로직 레벨과 다른 네거티브 로직입니다.
따라서 다음 그림을 완성하려면 컴퓨터의 9핀 RS232 직렬 포트를 마이크로컨트롤러에 직접 연결할 수 없습니다.
RS232 핀 설명:
1. 캐리어 감지 DCD(Data Carrier 감지) 2. 데이터 RXD 수신 3. 데이터 TXD 전송
4. 데이터 터미널이 DTR을 위한 준비가 되었습니다(데이터 터미널 준비 완료) 5. 신호 접지 6. 데이터 준비 DSR(데이터 세트 준비 완료)
7. RTS 전송 요청(보내기 요청) 8. CTS를 지우고 전송합니다(보내기를 완료했습니다) 9. 벨이 울리는 프롬프트 RI(울리는)
위 그림과 같이 RS232의 직렬 포트 배선에서는 핀 2, 3, 5가 해당 MAX232 핀에 연결되어 있어야 통신이 완료됩니다.
기술이 발전함에 따라 RS-232 직렬 포트 통신이 산업계에서 널리 사용됩니다. 그러나 상용 기술의 적용에서는 USB-UART 기술이 천천히 RS232 직렬 포트를 대체해 왔습니다.
그림과 같이 마이크로 컨트롤러와 컴퓨터 간의 통신을 구현하는 방법
이 경우 USB-직렬 포트 칩 CH340T를 사용하여 이 기능을 구현하는 개발 보드입니다.
마이크로 컨트롤러 포트 TXD는 점퍼 캡을 사용하여 USB-TX에 연결하고 동시에 CH340 핀 4 RXD 포트에 연결됩니다.
마이크로 컨트롤러 포트 RXD는 점퍼 캡을 사용하여 USB-RX에 연결되며 CH340의 3번 핀 TXD에 연결됩니다.
STC89C52 마이크로컨트롤러는 프로그램을 다운로드할 때 콜드 스타트가 필요하기 때문에 USB-RX와 CH340의 세 번째 핀 TXD 사이에 직렬로 4148 다이오드가 있음을 알 수 있습니다. 먼저 다운로드를 클릭한 다음 전원을 켜세요.
소위콜드 스타트 이는 전원이 꺼진 후 켜질 때까지 마이크로컨트롤러의 시작 프로세스를 의미하며, 핫 스타트는 마이크로컨트롤러의 전원이 항상 켜져 있음을 의미합니다. 콜드 스타트와 핫 스타트의 차이점은 다음과 같습니다. 콜드 스타트 중에는 마이크로 컨트롤러 내부 RAM의 값이 무작위인 반면, 핫 스타트 중에는 마이크로 컨트롤러 내부 RAM의 값이 변경되지 않습니다. 시작 전과 동일하게 유지됩니다.
전원을 켜는 순간 마이크로컨트롤러는 프로그램을 다운로드해야 하는지 여부를 먼저 감지합니다. 비록 마이크로컨트롤러의 VCC는 스위치에 의해 제어되지만 CH340T의 핀 3은 출력 핀이므로 그러한 것이 없는 경우입니다. 다이오드의 경우 전원이 꺼지면 스위치의 후속 마이크로컨트롤러가 작동하지 않습니다. CH340T의 핀 3은 마이크로컨트롤러의 P3.0(RXD) 핀에 연결되며 전류는 이 핀을 통해 후속 단계 회로로 흘러 커패시터를 충전합니다. 후속 단계에서 특정 전압이 발생합니다. 이 전압은 값이 약 2~3V에 불과하지만 정상적인 콜드 스타트에 영향을 미칠 수 있습니다. 다이오드를 추가하면 한편으로는 통신에 영향을 미치지 않지만 다른 한편으로는 이러한 역효과를 제거할 수 있습니다.
나는 마이크로컨트롤러 매뉴얼에서 P3.0이 준양방향 IO 포트라는 것을 배웠습니다.
빨간색 상자 부분은 준양방향 IO 포트입니다. , 내부 출력 비트가 로우 레벨일 때 NOT 게이트를 통해 트랜지스터의 베이스가 하이 레벨이 되고 트랜지스터가 켜지며(포화 전도에서는 CE 양단의 전압이 거의 동일함) IO가 발생합니다. 마이크로컨트롤러의 포트는 외부와 관계없이 로우 레벨을 출력합니다. 키 스위치를 누르거나 팝업해도 IO 포트는 로우를 유지합니다. 즉, 외부 신호에 의해 제어되지 않습니다.
내부 출력이 하이 레벨일 때 NOT 게이트를 통과한 후 트랜지스터의 베이스가 매우 낮고 트랜지스터가 도통되지 않습니다(CE 양쪽 끝의 저항이 매우 크고 저항 R은 비교하여 무시할 수 있음). it) 이때 IO 포트의 출력은 높습니다. 버튼을 누르면 IO 포트가 접지되고 IO 포트는 낮은 레벨을 출력합니다.
이를 통해 알 수 있는 것은 다음과 같은 경우에만 가능합니다.IO 포트 출력은 높은 수준입니다.언제,IO 포트의 출력은 외부 회로에 의해 제어됩니다.。
그러므로 우리는 P3.0의 내부 출력이 RXD 포트로 사용될 때 항상 높다는 것을 알고 있습니다.P3.1TXD 포트는 송신기 역할을 하며 그 포트는내부 출력 레벨필요에 따라 위아래로 변경할 수 있습니다.
및: TTL 수준의 경우
출력 단자: 하이 레벨 >=2.4V, 로우 레벨 <=0.4V;
수신 측: 하이 레벨 >=2.0V, 로우 레벨 <=0.8V.
COMS 레벨의 경우
출력 단자: 하이 레벨 = Vcc, 로우 레벨 = GND(Vcc는 전원 전압)
수신 측: 하이 레벨 >=0.7Vcc, 로우 레벨 <=0.2Vcc.
수신단의 논리 레벨과 출력단의 논리 레벨 사이에는 여전히 약간의 전압 차이가 있습니다. 이는 신호 전송 중에 발생하는 전압 강하 간섭이나 보호 회로의 존재로 인해 발생할 수 있으므로 다이오드를 추가하지 않습니다. 전송된 전압이 혼란스러운 논리적 영역에 있습니다.
IO 포트를 사용하여 UART 직렬 통신 시뮬레이션
상위 프로그램:
- # include<reg52.h>
-
- sbit PIN_RXD = P3^0; //接受引脚定义
- sbit PIN_TXD = P3^1; //发送引脚定义
-
- bit RxdorTxd = 0; //指示当前状态为接受还是发送
- bit RxdEnd = 0; //接受结束标志
- bit TxdEnd = 0; //发送结束标志
- unsigned char RxdBuf = 0; //接收缓冲区
- unsigned char TxdBuf = 0; //发送缓冲器
-
- void ConfigUART(unsigned int baud);
- void StartTXD(unsigned char dat);
- void StartRXD();
-
-
- void main()
- {
- EA = 1; //打开总中断
- ConfigUART(9600); //配置波特率为9600
-
- while(1)
- {
- while(PIN_RXD); //等待接收引脚出现低电平,即起始位
- StartRXD(); //启动接收
- while(!RxdEnd); //等待接受完成
- StartTXD(RxdBuf +1);//接受到的整数+1后,发送回去
- while(!TxdEnd); //等待发送结束
- }
- }
-
- /* 串口配置函数,baud-通信波特率 */
- void ConfigUART(unsigned int baud)
- {
- TMOD &= 0xF0; //清零T0的控制位
- TMOD |= 0x02; //配置T0为模式2
- TH0 = 256 - (11059200/12)/baud; //计数T0的重载值
- }
-
- /* 启动串行接受 */
- void StartRXD()
- {
- TL0 = 256 - ((256-TH0) >> 1);//接受启动时T0定时为半个波特率周期
- ET0 = 1; //使能T0中断
- TR0 = 1; //启动T0
- RxdEnd = 0; //清零接受结束标志
- RxdorTxd = 0; //设置当前状态为接受 1位发送
-
- }
-
- /* 启动串行发送,dat-待发送字节数据 */
- void StartTXD(unsigned char dat)
- {
- TxdBuf = dat; //待发送数据保存到发送缓冲器
- TL0 = TH0; //T0计算初值为重载值
- ET0 = 1; //使能T0中断
- TR0 = 1; //启动T0
- PIN_TXD = 0; //发送起始位
- TxdEnd = 0; //清零发送结束标志
- RxdorTxd = 1; //设置当前状态为发送
- }
-
- /*T0中断服务函数,处理串行发送和接收 */
- void interruptTimer0() interrupt 1
- {
- static unsigned char cnt = 0;
-
- if(RxdorTxd)
- {
- cnt++;
- if(cnt <= 8) //低位在先一次发送8bit数据位
- {
- PIN_TXD = TxdBuf & 0x01;
- TxdBuf >>= 1;
- }
- else if(cnt == 9) //发送停止位
- {
- PIN_TXD = 1;
- }
- else //发送结束
- {
- cnt = 0; //复位bit计数器
- TR0 = 0; //关闭T0
- TxdEnd = 1; //置发送结束标志
- }
- }
-
- else //串行接收处理
- {
- if(cnt == 0) // 处理起始位
- {
- if(!PIN_RXD) //起始位为0时,清零接收缓冲器,准备接受数据位
- {
- RxdBuf = 0;
- cnt++;
- }
- else //起始位为1(不为0)时,中止接收
- {
- TR0 = 0; //关闭T0
- }
- }
- else if(cnt <= 8) //处理8位数据位
- {
- RxdBuf >>= 1; //低位在先,所以将之前接收的位向右移
- if(PIN_RXD) //接收脚为1时,缓冲器最高位置1
- { //而为0时不处理即仍保持位移后的0
- RxdBuf |= 0x80;
- }
- cnt++;
- }
- else //停止位处理
- {
- cnt = 0; //复位bit计数器
- TR0 = 0; //关闭T0
- if(PIN_RXD) //停止位为1时,方认为数据有效
- {
- RxdEnd = 1; //置接收结束标志
- }
- }
- }
-
- }
업무 논리 맵
이 프로그램은 타이머 0을 사용하여 UART 직렬 통신을 시뮬레이션합니다.시뮬레이션 프로그램. 이 프로그램은 컴퓨터와 마이크로 컨트롤러 간의 통신을 구현합니다. 그 통신 결과는 컴퓨터가 전송한 데이터를 마이크로컨트롤러로 전송하는 것이고, 마이크로컨트롤러는 이 데이터에 1을 더해 다시 컴퓨터로 보낸다. 이 결과를 보여주기 위해 STC-ISP와 함께 제공되는 직렬 포트 디버깅 도우미를 사용하십시오.
먼저, 포트가 동일한지 확인하세요. 위의 그림은 모두 COM3이고, 보드율은 9600, 체크 비트는 NO, 데이터 비트는 8, 정지 비트는 1입니다. (여기서 설정한 것은 컴퓨터의 비트입니다. 직렬 포트 매개변수)
결과를 살펴보세요. 정상적인 의사소통이 가능합니다.타이머 0은 직렬 통신을 시뮬레이션합니다._bilibili_bilibili
이 프로그램의 작동 논리를 간략하게 설명하십시오.모듈 보내기예를 들어, 가장 낮은 비트부터 시작하여 0xAA =1010 1010을 보냅니다.
즉 TxdBuf = 1010 1010 프로그램을 보세요
- if(RxdorTxd)
- {
- cnt++;
- if(cnt <= 8) //低位在先一次发送8bit数据位
- {
- PIN_TXD = TxdBuf & 0x01;
- TxdBuf >>= 1;
- }
- else if(cnt == 9) //发送停止位
- {
- PIN_TXD = 1;
- }
- else //发送结束
- {
- cnt = 0; //复位bit计数器
- TR0 = 0; //关闭T0
- TxdEnd = 1; //置发送结束标志
- }
- }
첫 번째인터럽트 입력 cnt = 1
PIN_TXD = TxdBuf & 0x01, 즉 1010 1010 0000 0001의 AND 결과는 0xAA의 최하위 비트를 송신 포트에 할당하여 해당 레벨을 활성화하는 것입니다. 처음으로 인터럽트 TXD 포트에 들어가는 전압은 로우 레벨이며, 이 과정은 두 번째 인터럽트가 발생할 때까지 계속되는 것을 볼 수 있습니다.
그러면 TxdBuff가 오른쪽으로 한 비트 이동됩니다. 즉, TxdBuf = 0101 0101입니다.
그 다음에두 번째방해하다
숫자 = 2
PIN_TXD = 1 이번에는 송신 포트의 레벨이 High 레벨입니다.
전송량 = 0010 1010
그다음 세 번째, 네 번째까지8번째
숫자 = 8
PIN_TXD = 1로 설정된 레벨은 전송되는 데이터의 최상위 비트 1인 하이 레벨이다.
이때 TxdBuf = 0x00
이후9번째9번째 인터럽트 입력은 데이터 비트가 방금 전송되었으며 정지 비트 전송을 준비할 시간이라는 의미입니다.
따라서 PIN_TXD = 1이면 송신 포트가 상위 레벨로 직접 할당됩니다.
마지막 10번째 인터럽트는 정지 비트도 전송되었음을 나타냅니다.따라서 cnt Reset에는 0의 값이 할당되고, TR0에는 0의 값이 할당되며, 타이머 0은 꺼지고, TXDEnd = 1이 되며, 전송 종료 플래그는 1로 설정되어 완전한 데이터 프레임의 전송이 완료된다.
이후수신 모듈: 앞서 0xAA를 보냈는데, 이 함수의 값은 수신된 데이터에 1을 더한 결과이므로 수신된 데이터는 0xA9 =1010 1001입니다.
- void StartRXD()
- {
- TL0 = 256 - ((256-TH0) >> 1);//接受启动时T0定时为半个波特率周期
- ET0 = 1; //使能T0中断
- TR0 = 1; //启动T0
- RxdEnd = 0; //清零接受结束标志
- RxdorTxd = 0; //设置当前状态为0接收 1为发送
-
- }
- else //串行接收处理
- {
- if(cnt == 0) // 处理起始位
- {
- if(!PIN_RXD) //起始位为0时,清零接收缓冲器,准备接受数据位
- {
- RxdBuf = 0;
- cnt++;
- }
- else //起始位为1(不为0)时,中止接收
- {
- TR0 = 0; //关闭T0
- }
- }
- else if(cnt <= 8) //处理8位数据位
- {
- RxdBuf >>= 1; //低位在先,所以将之前接收的位向右移
- if(PIN_RXD) //接收脚为1时,缓冲器最高位置1
- { //而为0时不处理即仍保持位移后的0
- RxdBuf |= 0x80;
- }
- cnt++;
- }
- else //停止位处理
- {
- cnt = 0; //复位bit计数器
- TR0 = 0; //关闭T0
- if(PIN_RXD) //停止位为1时,方认为数据有效
- {
- RxdEnd = 1; //置接收结束标志
- }
- }
- }
데이터를 수신하는 과정은 실제로 유사하다는 것을 알 수 있으며, 이해하기 쉽도록 주로 cnt와 협력하기 위해 첫 번째 인터럽트를 0번째부터 시작하도록 표시했습니다.
그림에서 알 수 있듯이 0번째 인터럽트가 진입하는데 걸리는 시간은 미리 설정된 인터럽트 시간의 절반임을 알 수 있다. 이는 레벨 신호가 0인지 1인지 확인할 때 가장 빠른 레벨에 도달하면 되기 때문이다. 샘플링 시간에는 오류나 간섭이 발생할 수 있으므로 샘플링 지점은 일반적으로 신호 전송 시간의 중간 지점에 설정되며 그곳의 레벨 신호는 이 기간에 전송된 신호로 간주됩니다. 따라서 수신 모듈은 처음으로 시작 비트를 수신할 때 인터럽트 시간을 원래 시간의 절반으로 설정하기만 하면 모든 후속 신호 수집 지점이 중심 지점에 있도록 보장할 수 있습니다.
프로그램이 어떻게 설정되는지 살펴보겠습니다. TL0 = 256 - ((256-TH0) >> 1); //T0 타이밍은 시작 시 전송 속도 기간의 절반입니다.
256-TH0은 미리 설정된 인터럽트 시간입니다. 앞서 인터럽트 시간을 이전 시간의 절반으로 설정하려고 한다고 언급했습니다. 프로그램 작업은 이를 1비트 오른쪽으로 이동하는 것입니다. 8의 예를 들어보겠습니다. . 오른쪽으로 1비트 쉬프트하면 0000 0100 = 4가 된다. 오른쪽으로 1비트 쉬프트하면 숫자가 원래 값의 절반으로 바뀌는 것을 알 수 있다. 마찬가지로 왼쪽으로 1비트 쉬프트한 결과는 0001 0000 =16이 되는데, 이는 원래 숫자에 2를 곱한다는 뜻이다.
프로그램 프로세스 분석 시작
RxdorTxd가 0이면 else 함수를 입력합니다.0번째 인터럽트를 입력할 때 시간 영역에서 수신 모듈의 시작점은 시작 비트의 중간점입니다. 먼저 포트 전압이 정말 낮은지 확인하고, 그렇지 않은 경우 인터럽트를 끕니다. 왜 이런 일을 하는가?
수신 모듈이기 때문에 RXD의 전압은 마이크로컨트롤러에 의해 제어되지 않습니다. 이 경우 CH340T의 TXD 단자의 전압을 제어하는 컴퓨터에 의해 제어됩니다. 마이크로 컨트롤러의 RXD 전압은 CH340TXD 끝을 따릅니다. 수신 측에서는 수신된 정보가 간섭을 받을 수 있으므로 다시 확인해야 합니다.
그렇다면 cnt++이면 cnt=1입니다. RxdBuf = 0; 수신 버퍼를 0으로 지웁니다.
이후1위(실제로는 두 번째)이류 인터럽트 cnt = 1을 입력하고 else if() 함수를 입력하여 데이터를 버퍼에 단계별로 전송합니다. 이후 과정은 자세히 설명하지 않습니다. 관심 있는 독자라면 프로그램 로직에 따라 직접 진행해도 됩니다. 데이터가 실제로 낮은 비트 방식으로 버퍼 변수에 저장되고 그 다음에는 높은 비트 방식으로 저장될 수 있는지 확인하십시오. 이전 블로그 게시물로 인해 이 함수는 왼쪽 시프트 방법을 사용하여 먼저 데이터의 상위 비트를 저장합니다. 이 접근 방식은 다른 작업 방식을 상당히 보완합니다.
이 시점에서 프로그램은 타이머 0을 사용하여 UART 직렬 통신을 시뮬레이션합니다.
의사소통의 세 가지 기본 유형
단방향 통신: 한 쪽만 상대방에게 정보를 보낼 수 있으며, 상대방은 TV 리모컨, 라디오 방송 등의 정보를 다시 보낼 수 없습니다.
반이중 통신: 두 당사자 간에 데이터를 전송할 수 있으며 한 당사자만이 동시에 상대방에게 데이터를 보낼 수 있습니다. 예를 들어 워키토키는 일반적인 반이중 통신입니다. 위의 직렬 포트 시뮬레이션 프로그램은 반이중 통신으로도 이해될 수 있습니다.
전이중 통신: 데이터를 수신하면서 데이터를 보낼 수 있으며, 전화 통신과 같이 두 가지가 동시에 수행됩니다.
IO 포트 시뮬레이션 직렬 통신은 기본적으로 직렬 통신의 본질을 보여 주지만 마이크로 컨트롤러 프로그램은 마이크로 컨트롤러의 IO 포트에서 수신한 데이터를 지속적으로 감지하고 스캔해야 하며 이는 마이크로 컨트롤러의 실행 시간을 많이 차지합니다. 따라서 51 마이크로 컨트롤러 내부에는 자동으로 데이터를 수신하고 수신 후 알림을 보낼 수 있는 UART 모듈이 있습니다. 이를 올바르게 사용하려면 특수 기능 레지스터를 올바르게 구성해야 합니다.
SCON 직렬 제어 레지스터
이 경우에는 모드 1만 도입합니다. 즉, SM1 = 1, SM0 = 0으로 설정하는 것이 모드 1입니다. 이 모드는 이전 시뮬레이션 직렬 통신에서 사용된 데이터 프레임 형식(시작 비트 1개, 데이터 비트 8개, 정지 비트 1개)입니다.
아날로그 직렬 통신은 타이머 0을 사용하여 전송 속도를 표현합니다. STC89C52 UART 모듈 전송 속도는 타이머 T1 또는 타이머 T2에 의해서만 생성될 수 있지만 이는 아날로그 통신 개념과 완전히 다릅니다.
타이머 T2를 사용하는 경우 추가 구성 레지스터가 필요합니다. 기본적으로 타이머 T1이 사용됩니다.
프로그램 코드:
- # include<reg52.h>
-
- void ConfigUART(unsigned int baud);
-
- void main()
- {
- EA = 1;
- ConfigUART(9600); //配置波特率为9600
- while(1);
-
- }
- /* 串口配置函数,baud-通信波特率 */
- void ConfigUART(unsigned int baud)
- {
- SCON = 0x50; //0x50= 0101 0000 配置串口为模式1
- TMOD &= 0x0F; //清零T1的控制位
- TMOD |= 0x20; //0x20 = 0010 0000 配置T1的为模式2自动重载模式
- TH1 = 256 - (11059200/12/32)/baud; //计算T1的重载值
- TL1 = TH1; //设置初值
- ET1 = 0; //禁止T1中断
- ES = 1; //启动串口中断
- TR1 = 1; //启动T1定时器
- }
-
- /*UART中断服务函数 */
- void interruptUART() interrupt 4
- {
- if(RI) //接收到字节
- {
- RI = 0; //软件清0接收中断标志
- SBUF = SBUF+1;//接收的数据+1,左边是发送SBUF,右边是接收SBUF
-
- }
- if(TI)
- {
- TI = 0; //软件清0发送中断标志位
- }
-
- }
결과 비디오를 살펴보십시오.모듈 직렬 통신과 함께 제공_bilibili_bilibili
문제없이 정상적인 의사소통이 가능하다는 것을 보실 수 있으며, 프로그램에서 관련 내용을 간략하게 설명하겠습니다.
타이머 T1의 재부하 값 계산 공식은 다음과 같습니다.
TH1 = TL1 = 256 - 수정 발진기 값/12/2/16/보드 속도
인터럽트 간격 시간 = 수정 발진기 값/12/2/16/보드 속도 = 수정 발진기 값/12*(1/보드 속도)*(1/32)
수정 발진기 값/12는 1초 동안의 기계 주기 수를 의미하고, (1/보드율)은 1비트의 데이터를 전송하는 데 필요한 시간을 의미합니다.
수정 발진기 값/12*(1/보드 속도)는 1비트 데이터를 전송하는 데 필요한 기계 프로세서 수를 의미합니다.
마찬가지로 수정발진기 값/12*(1/보드율)*(1/32) 이 인터럽트 시간 = 1비트 데이터를 전송하는 시간의 1/32
즉, 1비트의 데이터 전송은 32시간 간격으로 나누어집니다.
계산 결과는 3입니다. 즉, 인터럽트 간격 = 3 머신 사이클입니다. 이 시간은 매우 짧습니다.
직렬 포트 모듈의 신호 샘플링 방식은 단일 신호를 16번 수집하고 7번째, 8번째, 9번째 신호 레벨을 추출하는 것이므로 3번 중 2번이 하이 레벨이면 데이터가 하이 레벨인 것으로 간주됩니다. 1이 됩니다. 레벨이 0이 두 번이면 이 비트는 0으로 간주됩니다. 이러한 방식으로 예상치 못한 간섭으로 인해 데이터를 잘못 읽은 경우에도 최종 데이터의 정확성이 여전히 보장될 수 있습니다.
아래 사진은 주로 설명의 편의를 위해 추천 블로그 글을 발췌한 것입니다.: 전송 속도 계산 공식
SMOD는 전력 레지스터 PCON에 의해 제어됩니다. 기본적으로 SMOD는 0입니다. 이를 위 공식에 대입하면 이전 초기값 해법 공식이 됩니다.
TH1 = TL1 = 256 - 수정 발진기 값/12/2/16/보드 속도
레지스터가 1 PCON |= 0x80으로 설정되면, 즉 SMOD가 1로 설정되면 위 공식과 같이 전송 속도가 두 배가 될 수 있습니다.
이때 T1의 초기값은 TH1 = TL1 = 256 - 수정진동자 값/12/16/보드율이 된다.
여기서 한 가지 꼭 짚고 넘어가야 할 점은: PCON 레지스터를 사용하여 파동 속도를 두 배로 제어하려면 초기 값 공식을 다음과 같이 작성해야 합니다.
TH1 = TL1 = 256 - 수정 발진기 값/12/2/16/보드 속도는 단지
현재 다시 로드 값은 TH1=256 - (11059200/12/32)/baud =256-(11059200/12/16)/(2*buad) baud*2=4800*2=9600, 9600이 현재 프로그램 보드입니다. 비율
초기 값을 다시 로드하는 회사가 TH1 = TL1 = 256 - 수정 발진기 값/12/16/보드 속도라고 쓴다면 현재 보드 속도는 9600이 아닌 여전히 4800입니다.직렬 통신 소프트웨어를 사용하여 통신 전송 속도를 9600으로 설정하면 전송됩니다.결과가 틀렸어。
비디오 보기:전송 속도 관련_bilibili_bilibili
9600의 전송 속도에 대한 시간 간격은 단지 3개의 기계 주기이고 14400의 시간 간격은 2개의 기계 주기임을 알 수 있습니다. 전송 속도가 높을 경우 시간 간격은 1 기계 사이클보다 작을 수 있음을 알 수 있습니다. 따라서 또 다른 작업 모드가 있습니다. 즉, PCON의 최고 비트가 1로 설정된 후 ConfigUART(9600)입니다. 현재 전송 속도는 19200이지만 시간 간격은 원래 9600 전송 속도의 시간 간격입니다. 3개의 기계 사이클.
타이머 0 시뮬레이션 직렬 통신과 직렬 통신 모듈의 작업에는 여전히 많은 차이점이 있다는 점을 기억해야 합니다. 직렬 통신 모듈은 하나의 입력 및 출력을 완료하고 두 개의 직렬 통신 중단만 입력합니다. RI가 1로 설정된 경우 한 번, TI가 1로 설정된 경우 한 번, 소프트웨어에 의해 지워집니다. 더 이상 전송 프로세스에 주의를 기울이지 않고 전송 완료 여부에만 집중하고 전송이 완료되면 신호를 보냅니다.
직렬 통신의 송수신 회로는 물리적으로 두 개의 동일한 SBUF 레지스터를 갖고 있으며, 그 주소 역시 0x99이지만 하나는 송신 버퍼로 사용되고 다른 하나는 수신 버퍼로 사용된다. 즉, 방이 2개가 있고, 두 방의 집번호가 동일합니다. 그 중 한 방은 들어갈 수 있지만 다른 한 방은 나갈 수는 있지만 들어갈 수는 없습니다. 이러한 방식으로 UART의 전이중 통신은 서로 간섭 없이 이루어질 수 있습니다. 그러나 논리적으로는 매번 SBUF만 작동하며, 마이크로 컨트롤러는 "읽기" 또는 "쓰기" 작업을 수행하는지에 따라 SBUF를 수신할지 아니면 SBUF를 보낼지 자동으로 선택합니다.
직렬 통신 프로그램의 기본 단계:
1. 직렬 포트를 모드 1로 구성합니다.
2. 타이머 T1을 자동 재설치 모드인 모드 2로 구성합니다.
3. 전송 속도를 기준으로 TH1과 TL1의 초기 값을 계산합니다. 필요한 경우 PCON을 사용하여 전송 속도를 두 배로 늘릴 수 있습니다.
4. 타이머 제어 레지스터 TR1을 열고 타이머가 실행되도록 합니다.참고: 직렬 포트 인터럽트를 사용할 때 타이머 2 직렬 포트 인터럽트를 사용하지 않는 한 타이머 1 인터럽트는 더 이상 활성화될 수 없습니다.