时钟--单片机的心跳

什么是时钟

时钟,可以理解为人的心跳,它确定着系统的运行速度,也即我们外设的运行速度,时钟越快功耗越大,所以在32的时钟系统比较复杂,为的是降低功耗,这部分外设我们称为:RCC (reset clock control 复位和时钟控制器)。

系统框图刨析

image-20221228222743278

系统时钟(SYSCLK)

image-20221228222943178

系统时钟来源可以是:HSI、PLLCLK、HSE,然后系统时钟在通过AHB预分频器分频给到不同外设总线,比如APB1 APB2…最大为72Mhz,所以我们现在要来看的就是这三个时钟源(总共五个,下面一一列举)

时钟源

HSE 外部高速时钟信号

可以由有源或无源晶振提供,一般是4-16MHZ,如果选择有源晶振,时钟从OSC_IN进入,无源时,从OSC_IN 和OSC_OUT进入,一般接入8M的无源晶振。

image-20221228224242749

HSI 内部高速时钟信号

HSI 是高速内部时钟,RC 振荡器,频率为 8MHz

image-20221228231816071

LSI

LSI 是低速内部时钟,RC 振荡器,频率为 40kHz。独立看门狗的时钟源只能是 LSI,同 时 LSI 还可以作为 RTC 的时钟源。

image-20221228233215882

LSE

LSE 是低速外部时钟,接频率为 32.768kHz 的石英晶体,主要作为RTC的时钟源

image-20221228233401577

PLL

PLL 为锁相环倍频输出,其时钟输入源可选择为 HSI/2、HSE 或者 HSE/2。倍频可选择为2~16 倍,但是其输出频率最大不得超过 72MHz

image-20221228233608126

image-20230101155741021

MCO 是 STM32 的一个时钟输出 IO(PA8),它可以选择一个时钟信号输出,这个可以用于给外部系统提供时钟

分频给到各个外设使用

image-20230101160409955

当系统时钟确实了使用哪个时钟源之后,接下来就要经过AHB预分频器,接着就是各个分支上的预分频器,以APB1预分频器为例,如果分频系数是2,那就要将当前频率除以2.

其中需要理解的是 APB1 和 APB2 的区别,APB1 上面连接的是低速外设,包括电源接口、备份接口、CAN、USB、I2C1、I2C2、UART2、UART3 等等,APB2 上面连接的是高速外设包括 UART1、SPI1、Timer1、ADC1、ADC2、所有普通 IO 口(PA~PE)、第二功能 IO 口等。

使用CUBEMX配置

image-20230101162802939

选择HSE和LSE的激励源,因为这两都是靠外部激励工作的,这里直接选晶振

image-20230101164516727

image-20230101163813543

(img-HHzZYRSc-1672562909433)]

[外链图片转存中…(img-1zzPrZAD-1672562909434)]

配置的话就按从左往右顺序来,记得考虑一些时钟的最大值,然后主要就是做点乘除运算而已,一般系统时钟来源我们选择PLL。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是天祥TX-1C单片机开发板的时钟程序示例: ```c #include <reg52.h> #define uchar unsigned char #define uint unsigned int sbit SCL=P2^1; //定义 I2C 时钟线引脚 sbit SDA=P2^0; //定义 I2C 数据线引脚 void I2C_Start(void); void I2C_Stop(void); void I2C_SendByte(uchar dat); uchar I2C_RecvByte(void); void Delay1ms(uint cnt); void DS1307_Init(void); void DS1307_Write(uchar addr, uchar dat); uchar DS1307_Read(uchar addr); void DisplayTime(void); uchar code WeekDayTable[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"}; //星期表 uchar code timeData[]={0x00,0x00,0x00,0x00,0x00,0x00,0x00}; //保存时间日期数据 uchar i; //循环计数变量 void main() { DS1307_Init(); //初始化 DS1307 while(1) { DisplayTime(); //显示时间 } } void I2C_Start(void) { SDA=1; //数据线高电平 SCL=1; //时钟线高电平 Delay1ms(1); //延时 SDA=0; //数据线低电平,发出起始信号 Delay1ms(1); //延时 SCL=0; //时钟线低电平,准备发送或接收数据 } void I2C_Stop(void) { SDA=0; //数据线低电平 SCL=1; //时钟线高电平 Delay1ms(1); //延时 SDA=1; //数据线高电平,发出停止信号 Delay1ms(1); //延时 } void I2C_SendByte(uchar dat) { uchar i; for(i=0; i<8; i++) { SDA=dat>>7; //发送数据的最高位 dat<<=1; //数据左移一位,准备发送下一位数据 SCL=1; //时钟线高电平,数据线上的数据被采样 Delay1ms(1); //延时 SCL=0; //时钟线低电平,准备发送或接收下一位数据 Delay1ms(1); //延时 } } uchar I2C_RecvByte(void) { uchar i, dat=0; SDA=1; //数据线高电平,准备接收数据 for(i=0; i<8; i++) { dat<<=1; //数据左移一位,准备接收下一位数据 SCL=1; //时钟线高电平,数据线上的数据被采样 Delay1ms(1); //延时 if(SDA) //如果数据线上的数据为高电平 { dat|=0x01; //将数据线上的数据存入 dat 的最低位 } SCL=0; //时钟线低电平,准备发送或接收下一位数据 Delay1ms(1); //延时 } return dat; } void Delay1ms(uint cnt) { uint i, j; for(i=0; i<cnt; i++) { for(j=0; j<110; j++); } } void DS1307_Init(void) { uchar i; I2C_Start(); //发起 I2C 起始信号 I2C_SendByte(0xd0); //发送器件地址+写命令 I2C_SendByte(0x07); //发送内部地址:时钟芯片控寄存器 I2C_SendByte(0x00); //发送控字节:清除 CH、RS0、RS1 位 I2C_Stop(); //发起 I2C 停止信号 I2C_Start(); //发起 I2C 起始信号 I2C_SendByte(0xd0); //发送器件地址+写命令 I2C_SendByte(0x00); //发送内部地址:秒 for(i=0; i<7; i++) { I2C_SendByte(timeData[i]); //发送时间数据 } I2C_Stop(); //发起 I2C 停止信号 } void DS1307_Write(uchar addr, uchar dat) { I2C_Start(); //发起 I2C 起始信号 I2C_SendByte(0xd0); //发送器件地址+写命令 I2C_SendByte(addr); //发送内部地址 I2C_SendByte(dat); //发送数据 I2C_Stop(); //发起 I2C 停止信号 } uchar DS1307_Read(uchar addr) { uchar dat; I2C_Start(); //发起 I2C 起始信号 I2C_SendByte(0xd0); //发送器件地址+写命令 I2C_SendByte(addr); //发送内部地址 I2C_Start(); //发起 I2C 起始信号 I2C_SendByte(0xd1); //发送器件地址+读命令 dat=I2C_RecvByte(); //接收数据 I2C_Stop(); //发起 I2C 停止信号 return dat; } void DisplayTime(void) { uchar year, month, day, weekDay, hour, minute, second; year=DS1307_Read(0x06); //读取年份 month=DS1307_Read(0x05); //读取月份 day=DS1307_Read(0x04); //读取日期 weekDay=DS1307_Read(0x03); //读取星期 hour=DS1307_Read(0x02); //读取小时 minute=DS1307_Read(0x01); //读取分钟 second=DS1307_Read(0x00); //读取秒钟 printf("%d/%d/%d %s %d:%d:%d\n", 2000+year, month, day, WeekDayTable[weekDay-1], hour, minute, second); //格式化输出时间 Delay1ms(1000); //延时1秒 } ``` 该程序使用了DS1307实时时钟芯片来实现时钟功能,使用I2C总线进行通信。程序中的`DS1307_Init()`函数用于初始化DS1307,将控寄存器清零,并将时间数据写入DS1307的寄存器中。`DS1307_Write()`和`DS1307_Read()`函数用于向DS1307写入数据和从DS1307读取数据。`DisplayTime()`函数用于读取DS1307中的时间数据并将其格式化输出。 该程序需要在连接好DS1307实时时钟芯片的天祥TX-1C单片机开发板上运行,才能正常显示时间。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值