51单片机——IO拓展(串转并)-74HC595 小白详解

时间:2025-03-07 10:12:06
  • /********************************************************************
  • ****************** 实验名称:IO 扩展(串转并)实验-74HC595
  • 接线说明
  • 实验现象:下载程序后,8*8LED 点阵以一行循环滚动显示
  • 注意事项:LED 点阵旁的 J24 黄色跳线帽短接到 GND 一端
  • *********************************************************************
  • ******************/
  • #include ""
  • typedef unsigned int u16; //对系统默认数据类型进行重定义
  • typedef unsigned char u8;
  • //定义 74HC595 控制管脚
  • sbit SRCLK=P3^6; //移位寄存器时钟输入
  • sbit rCLK=P3^5; //存储寄存器时钟输入
  • sbit SER=P3^4; //串行数据输入
  • #define LEDDZ_COL_PORT P0 //宏定义LED点阵列控制端口
  • //定义ghc595_buf[]数组把每次输出的数据储存在里面,传入到hc595_write_data函数
  • u8 ghc595_buf[8]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
  • /********************************************************************
  • ***********
  • * 函 数 名 : delay_10us
  • * 函数功能 : 延时函数,ten_us=1 时,大约延时 10us
  • * 输 入 : ten_us
  • * 输 出 : 无
  • *********************************************************************
  • **********/
  • void delay_10us(u16 ten_us)
  • {
  • while(ten_us--);
  • }
  • /********************************************************************
  • ***********
  • * 函 数 名 : delay_ms
  • * 函数功能 : ms 延时函数,ms=1 时,大约延时 1ms
  • * 输 入 : ten_us
  • * 输 出 : 无
  • * for(j=110;j>0;j--)在for(i=ms;i>0;i--)嵌套这,delay_ms(500),
  • * 时候ms=500,i=ms 所以i=500,进入for(i=ms;i>0;i--),
  • * 然后在执行for(j=110;j>0;j--),进行循环110次一直到j=0,
  • * 在退出for(j=110;j>0;j--),
  • * 在重新执行for(i=ms;i>0;i--),一直到到i=0时候,退出for(i=ms;i>0;i--)
  • *********************************************************************
  • **********/
  • void delay_ms(u16 ms)
  • {
  • u16 i,j;
  • for(i=ms;i>0;i--)
  • for(j=110;j>0;j--);
  • }
  • /********************************************************************
  • ***********
  • * 函 数 名 : hc595_write_data(u8 dat)
  • * 函数功能 : 向 74HC595 写入一个字节的数据
  • * 输 入 : dat:数据
  • * 输 出 : 无
  • *********************************************************************
  • **********/
  • /********************************************************************
  • *******************SER=dat>>7(dat向右移7位后赋值给SER)详解*************
  • dat是后面要输入的一个字节的数据,hc595_write_data(0x00)如后面的
  • hc595_write_data(0x01),这时候dat就是(0x01)当dat=00000001(0x01)时候,
  • 高位是0,低位是1 ,对应按照QH-QA,就是QH低电平,QA高电平,但是74HC595的传输
  • 规律是先从高位在到低位的传输,左移1就传给了QH,这样QH高电平,QA为低电平,我们
  • 想要QH输入低电平怎么办呢?就用把dat>>7,按照右移的规则(对于不带字符的数值,
  • 向右移位时,会在左边的空位填充0。)那(0x01)就变成0(0X00)一个字节八位都是0
  • 这样传输给QH就是低电平,
  • *********************************************************************
  • **********/
  • /********************************************************************
  • *******************dat<<=1(dat向左移一位后在赋值给dat)详解*************
  • 但是for(i=0;i<8;i++)循环8次,八位就都是0,QH-QA都是低电平,这样是不对的,
  • 我们是要QA输入高电平,这时候就需要每次循环的时候dat<<=1,每次SER=dat>>7;
  • 执行完dat<<=1,例如开始dat=(0x01),执行完SER=dat>>7后,在把dat<<=1(dat向
  • 左移一位后在赋值给dat),这样下次在进入SER=dat>>7时候,dat就是dat<<=1(0X02)
  • 一直倒循环到第7次时候dat也左移了7位,dat变成了10000000(0x80),这时候在进入
  • SER=dat>>7时候,SER就等于1,对应QA传输,就按照hc595_write_data(0x01)的一样
  • 低位1,其余都是0的输入。
  • *********************************************************************
  • **********/
  • /********************************************************************
  • *******************SRCLK=0,SRCLK=1详解*******************************
  • 74HC595芯片的传输规则,SER写入数据后,要移位寄存器(SRCLK)时钟上升沿,才能把
  • 数据送到存储寄存器进行输出,所有我们要先给SRCLK一个低电平,在给一个高电平,就产
  • 生了上升沿,那我们就先SRCLK=0送入低电平;中间延时下,在SRCLK=1送入高电平,
  • 一低一高,这样就产生时钟上升沿,就把数据送入到存储寄存器,每次循环都送入存储寄存器,
  • 循环8次,就把8位的数据都送到存储寄存器中了。
  • 中间的delay_10us(1);这里的延时,不要也可以,但是以防出错这里延时下
  • *********************************************************************
  • **********/
  • /********************************************************************
  • *******************rCLK=0,rCLK=1详解*******************************
  • 74HC595芯片的传输规则,如果将前面写入存储寄存器数据输出,那存储寄存器时钟要
  • 上升沿才能输出,那我们就先rCLK=0送入低电平;中间延时下,在rCLK=1送入高电平,
  • 一低一高,这样产生时钟上升沿,就将前面写入到寄存器的数据输出了。
  • 中间的delay_10us(1);这里的延时,不要也可以,但是以防出错这里延时下
  • *********************************************************************
  • **********/
  • void hc595_write_data(u8 dat)
  • {
  • u8 i=0;
  • for(i=0;i<8;i++)//循环 8 次即可将一个字节写入寄存器中
  • {
  • SER=dat>>7;//优先传输一个字节中的高位
  • dat<<=1;//将低位移动到高位
  • SRCLK=0;
  • delay_10us(1);
  • SRCLK=1;
  • delay_10us(1);//移位寄存器时钟上升沿将端口数据送入寄存器中
  • }
  • rCLK=0;
  • delay_10us(1);
  • rCLK=1;//存储寄存器时钟上升沿将前面写入到寄存器的数据输出
  • }
  • /********************************************************************
  • ***********
  • * 函 数 名 : main
  • * 函数功能 : 主函数
  • * 输 入 : 无
  • * 输 出 : 无
  • *********************************************************************
  • **********/
  • /********************************************************************
  • *******************LEDDZ_COL_PORT=0x00详解*******************************
  • 我们在DPa---DPh输入的是高电平,如果我们要将LED灯点亮,我们要把P0端口全部设为低电
  • 平,即 LED 阴极为低电平,前面我们宏定义了P0端口,所以这里LEDDZ_COL_PORT=0x00就可以
  • *********************************************************************
  • **********/
  • /********************************************************************
  • *******************hc595_write_data(ghc595_buf[i])详解***************
  • 我们定义了,数组ghc595_buf[],把每次输出的数据储存在里面,通过for循环,依次
  • 输出,每次写入新数据之前,要先消除前面输出数据点亮LED进行消影,所以每次在输入
  • 数据之前,我们先把所有DPa---DPh输入低电平,来消除前面寄存器缓存数据,之后在
  • 在写入新的数据:这样就产生了,LED点阵,从下到上,每行依次点亮
  • *********************************************************************
  • **********/
  • void main()
  • {
  • u8 i=0;
  • LEDDZ_COL_PORT=0x00;//将 LED 点阵列全部设置为 0,即 LED 阴极为低电平
  • while(1)
  • {
  • for(i=0;i<8;i++)
  • {
  • hc595_write_data(0x00);//消除前面寄存器缓存数据
  • hc595_write_data(ghc595_buf[i]);//写入新的数据
  • delay_ms(500);//延时 500ms
  • }
  • }
  • }