PIC通信与实时时钟编程详解
1. PIC间UART通信原理与程序分析
PIC(Peripheral Interface Controller)微控制器可利用通用异步收发传输器(UART)与终端设备进行通信。在PIC - PIC UART项目中,两个PIC通过UART实现信息交互。
1.1 程序原理
- 两个PIC首先在LCD上显示开场语句。
- 接着进入无限循环。PIC1等待重复按钮变高后,若PIC2将CTS输入驱动到逻辑‘0’,则向PIC2发送第一条消息“Hi”。
- 发送消息后,设置约135ms的延迟,确保重复按钮回到逻辑‘0’。
- 再次等待重复按钮变高,PIC1才能发送下一条消息。在此之前,PIC2应发送其第一条消息。
- 此过程不断重复,PIC1接收PIC2的两条消息,并向PIC2发送自己的消息。
1.2 PIC2程序代码
/*This is a basic program to use the UART
To communicate with two PICs
This is the program for PIC two
Written by H H Ward for the PIC18F4525
Dated 03/04/2021*/
#include <xc.h>
#include <conFigInternalOscNoWDTNoLVP.h>
#include <4bitLCDDemoBoard.h>
unsigned char n, count, newdatain = 0;
unsigned char mess[30], *messpointer;
#define repeatButton PORTAbits.RA4
#define RTS PORTBbits.RB0
#define CTS PORTBbits.RB1
void shortdelay ()
{
TMR0 = 0;
while (TMR0 < 255);
}
void delay (unsigned char t)
{
for (n = 0; n < t; n ++)
{
TMR0 = 0;
while (TMR0 < 255);
}
}
void sendDeviceString(const char* meshw)
{
while(*meshw)
{
while (CTS);
RTS = 1;
while(!TXIF);
TXREG = (*meshw++);
shortdelay ();
RTS = 0;
}
}
void interrupt isr1 ()
{
if (PIR1bits.RCIF == 1)
{
RTS = 1;
do
{
if(OERR)
{
CREN = 0;
CREN = 1;
}
while(!RCIF);
newdatain = RCREG;
lcdData = newdatain;
lcdOut ();
shortdelay ();
}while (RCIF);
RTS = 0;
}
}
void main ()
{
PORTA = 0;
PORTB = 0;
PORTC = 0;
PORTD = 0;
TRISA = 0b00010000;
TRISB = 0x02;
TRISC = 0b10000000;
TRISD = 0x00;
ADCON0 = 0x00;
ADCON1 = 0x0F;
OSCCON = 0b01110000;
OSCTUNE = 0b10000000;
T0CON = 0b11000111;
INTCON = 0b11000000;
PIE1bits.RC1IE = 1;
TXSTA = 0b00100000;
RCSTA = 0b10010000;
BAUDCON = 0b00000000;
SPBRG = 12;
messpointer = mess;
setUpTheLCD ();
clearTheScreen ();
writeString ("Coded PIC2");
line2 ();
while (1)
{
while (repeatButton);
while (CTS);
sendDeviceString ("Hello");
delay (10);
while (repeatButton);
while (CTS);
sendDeviceString ("OK Will Do");
delay (10);
while (repeatButton);
delay (10);
}
}
2. 实时时钟(RTC)编程
实时时钟(RTC)在许多应用中至关重要,可用于同步事件、创建日历等。以下介绍使用PIC18F4525实现RTC的方法。
2.1 RTC原理
使用外部32.768kHz晶体振荡器作为timer1的时钟源,timer1设置为16位定时器,用于计数时钟脉冲。
2.2 T1CON控制寄存器
T1CON控制寄存器的各比特位功能如下:
| 比特位 | 功能 | 说明 |
| ---- | ---- | ---- |
| 7 RD16 | 16位读写模式使能位 | 逻辑‘1’:TMR1作为16位读写操作;逻辑‘0’:TMR1作为8位读写操作 |
| 6 T1RUN | 定时器1系统时钟状态位 | 逻辑‘1’:设备时钟源自timer1振荡器;逻辑‘0’:设备时钟源自其他地方 |
| 5 T1CKPS1 | 定时器1时钟预分频选择1 | 与T1CKPS0配合使用 |
| 4 T1CKPS0 | 定时器1时钟预分频选择0 | 与T1CKPS1配合使用,提供四种不同分频比 |
| 3 T1OSCEN | 定时器1振荡器使能位 | 逻辑‘1’:timer1振荡器启用;逻辑‘0’:振荡器禁用 |
| 2 T1SYNC | 定时器1外部时钟输入同步选择位 | 依赖于TMR1CS位,TMR1CS为‘1’时,逻辑‘1’:不同步外部时钟输入;逻辑‘0’:同步外部时钟输入 |
| 1 TMR1CS | 定时器1时钟源选择位 | 逻辑‘1’:外部时钟;逻辑‘0’:内部时钟(Fosc/4) |
| 0 TMR1ON | 定时器1开启位 | 逻辑‘1’:开启timer1;逻辑‘0’:关闭timer1 |
定时器1时钟预分频比设置如下:
| T1CKPS1 | T1CKPS0 | 预分频比 |
| ---- | ---- | ---- |
| 0 | 0 | 1:1 不分频 |
| 0 | 1 | 1:2 二分频 |
| 1 | 0 | 1:4 四分频 |
| 1 | 1 | 1:8 八分频 |
为使用外部晶体振荡器作为timer1的时钟源,需将T1CON设置为0b00001111,具体操作如下:
- 位0设置为逻辑‘1’,开启timer1。
- 位1设置为逻辑‘1’,使用外部振荡器作为timer1的时钟源。
- 位2设置为逻辑‘1’,不同步外部时钟输入。
- 位3设置为逻辑‘1’,启用外部振荡器电路。
- 位4和5设置为逻辑‘0’,不分频振荡器。
- 位6设置为逻辑‘0’,设备时钟不源自timer1振荡器。
- 位7设置为逻辑‘0’,timer1寄存器由两个8位寄存器TMR1H和TMR1L级联组成。
2.3 RTC程序代码
/*
* File: Real Time Clock.c
Author: H. H. Ward
*Written for the PIC18F4525
Created on 24 August 2020, 12:09
*/
#include <xc.h>
#include <conFigInternalOscNoWDTNoLVP.h>
#include <4bitLCDDemoBoard.h>
unsigned char secunits = 0X30, sectens = 0X30, minunits = 0X30, mintens = 0X30, hourunits = 0X30, hourtens = 0X30;
void delay (unsigned char t)
{
for (n = 0; n < t; n ++)
{
TMR0 = 0;
while (TMR0 < 255); //a 30msec delay
}
}
void interrupt isr1 ()
{
secunits ++;
PIR1bits.TMR1IF = 0;
TMR1H = 0X80;
}
void main ()
{
PORTA = 0;
PORTB = 0;
PORTC = 0;
PORTD = 0;
TRISA = 0b00001111;
TRISB = 0b00000000;
TRISC = 0b10010010;
TRISD = 0x00;
ADCON0 = 0b00000000;
ADCON1 = 0b00001111;
OSCTUNE = 0x80;
OSCCON = 0x70;
T0CON = 0XC7;
T1CON = 0b00001111;
INTCON = 0b11000000;
PIE1bits.TMR1IE = 1;
PORTB = 0;
setUpTheLCD ();
writeString ("Hello");
line2 ();
while (1)
{
if (secunits == 0X3A)
{
secunits = 0X30;
sectens ++;
if ( sectens == 0X36)
{
sectens = 0X30;
minunits ++;
if (minunits == 0X3A)
{
minunits = 0X30;
mintens ++;
if (mintens == 0X36)
{
mintens = 0X30;
hourunits ++;
if(hourunits == 0X3A)
{
hourunits = 0X30;
hourtens ++;
}
}
}
}
}
if (hourtens == 0X32 & hourunits == 0X34 )
{
hourtens = 0x30;
hourunits= 0x30;
}
line2 ();
lcdData = hourtens;
lcdOut ();
lcdData = hourunits;
lcdOut ();
lcdData = 0x3A;
lcdOut ();
lcdData = mintens;
lcdOut ();
lcdData = minunits;
lcdOut ();
lcdData = 0x3A;
lcdOut ();
lcdData = sectens;
lcdOut ();
lcdData = secunits;
lcdOut ();
lcdData = 0xA0;
lcdOut ();
}
}
2.4 RTC程序分析
- 主原理 :使用timer1计数外部晶体振荡器的时钟脉冲,timer1设置为16位定时器,计数结果存储在TMR1H和TMR1L中。
- 计数时间计算 :外部晶体振荡器频率为32.768kHz,一个计数周期为30.5176ms,计数从0到65535需要2秒。为实现1秒计数,让timer1从0b1000000000000000开始计数。
- 中断处理 :当timer1计数达到最大值并溢出时,TMR1IF标志位设置为逻辑‘1’。为利用此溢出事件,需启用timer1中断,包括全局中断和外设中断。
- 中断服务例程(ISR) :在ISR中,将secunits变量加1,清除TMR1IF标志位,并将TMR1H加载为0X80,使timer1从后半部分开始计数。
- LCD显示 :在无限循环中,检查secunits的值,若达到0X3A(ASCII码为10),则将其重置为0X30,并将sectens加1。类似地,处理分钟和小时的进位。最后,将时间信息发送到LCD显示。
以下是RTC程序的流程:
graph TD;
A[初始化] --> B[开启全局和外设中断];
B --> C[设置timer1];
C --> D[等待timer1溢出中断];
D --> E[执行中断服务例程];
E --> F[更新时间变量];
F --> G[检查进位];
G --> H[更新LCD显示];
H --> D;
通过以上分析,我们详细了解了PIC间UART通信和实时时钟编程的原理与实现方法。这些技术在嵌入式系统开发中具有重要应用价值,可用于实现各种时间敏感的功能。
3. 关键技术点总结与操作步骤梳理
3.1 PIC间UART通信关键技术点
- 信号交互 :PIC1和PIC2通过CTS(清除发送)和RTS(请求发送)信号进行通信协调。PIC2将CTS输入驱动到逻辑‘0’时,PIC1才能发送消息。
- 延迟设置 :发送消息后设置延迟,确保重复按钮回到逻辑‘0’,避免误操作。
-
消息发送
:使用
sendDeviceString函数发送字符串消息,发送过程中会等待CTS信号为低,并设置RTS信号为高。
3.2 PIC间UART通信操作步骤
-
初始化设置
:对端口、寄存器等进行初始化,如设置
PORTA、PORTB等为初始值,配置TRISA、TRISB等端口方向。 -
LCD初始化
:调用
setUpTheLCD和clearTheScreen函数初始化LCD,并显示开场语句。 - 进入循环 :在无限循环中,等待重复按钮变高,检查CTS信号,发送消息,设置延迟。
以下是PIC - PIC UART通信的操作步骤流程图:
graph TD;
A[初始化设置] --> B[LCD初始化];
B --> C[进入无限循环];
C --> D[等待重复按钮变高];
D --> E[检查CTS信号];
E --> F{CTS为低?};
F -- 是 --> G[发送消息];
F -- 否 --> D;
G --> H[设置延迟];
H --> D;
3.3 RTC编程关键技术点
- 时钟源选择 :使用外部32.768kHz晶体振荡器作为timer1的时钟源,确保时钟精度。
- 中断处理 :利用timer1溢出中断来更新时间变量,实现精确计时。
- 时间进位处理 :在无限循环中检查时间变量的进位情况,确保时间显示的正确性。
3.4 RTC编程操作步骤
-
初始化设置
:对端口、寄存器等进行初始化,如设置
PORTA、PORTB等为初始值,配置T1CON寄存器。 -
启用中断
:设置
INTCON和PIE1bits.TMR1IE启用全局中断和timer1外设中断。 -
LCD初始化
:调用
setUpTheLCD和writeString函数初始化LCD并显示初始信息。 - 进入循环 :在无限循环中,检查时间变量的进位情况,更新LCD显示。
4. 代码优化建议
-
PIC间UART通信代码优化
- 延迟优化 :可以根据实际情况调整延迟时间,避免不必要的等待。
- 错误处理 :在消息发送和接收过程中增加错误处理机制,提高通信的稳定性。
-
RTC编程代码优化
- 时间设置功能 :增加时间设置功能,允许用户手动设置时钟时间。
- 显示优化 :优化LCD显示格式,提高显示的可读性。
5. 总结
本文详细介绍了PIC间UART通信和实时时钟(RTC)编程的原理、程序代码和操作步骤。通过对PIC - PIC UART通信的分析,我们了解了如何通过UART实现两个PIC之间的信息交互;通过对RTC编程的讲解,我们掌握了如何使用外部晶体振荡器和timer1实现精确的实时时钟功能。这些技术在嵌入式系统开发中具有广泛的应用前景,可用于实现各种时间敏感的功能,如事件同步、日历管理等。在实际应用中,我们可以根据具体需求对代码进行优化,提高系统的性能和稳定性。
超级会员免费看
66

被折叠的 条评论
为什么被折叠?



