一个破流水灯程序看了两天了,void WriteByte(unsigned char data)这部分还是没看懂,力天电子上面介绍说这部分三端口的数据输入,选出8位的串行数据。
选择16,17,18,19四个控制位,主要跟电路图的连接有关,4块74HC595,组成32位(如图所示),从下往上依次是0~31为,图中写反了。因此到D13对应的引脚应该是16,D12对应的是17,D11对应的是18,D10对应的是19. 当16,17,18,19分别为低电平时二极管才能够导通发光。高电平时熄灭
1#include <NXP/iolpc2148.h>
2#define SCLK 0x01<<24 //指定P1.24管脚,通过 IO1DIR |= SCLK;可判断是IO1端口,而不是IO0端口3#define MISO 0x01<<5 //指定P0.5口
4#define MOSI 0x01<<6 //指定P0.6口
5#define RCK 0x01<<7 //指定P0.7口
6void Delayn(unsigned long n); //unsigned long n是一个入口函数
7void HC595_Init(void);
8void Write595(void);
9unsigned int HC595_DATA = 0;
10int main(void)
11{
12 //初始化74HC595
13 HC595_Init();
14 //主循环
15 while(1)
16 {
17 HC595_DATA &=~(1<<16);Write595(); //首先1左移16位,得到0000 0000 0000 0001 0000 0000 0000 0000,取反(~)得到1111 1111 1111 1110 1111 1111 1111 1111
//然后跟HC595_DATA取与(&),HC595_DATA的值为0xFFFFFFFF(在42行),得到1111 1111 1111 1110 1111 1111 1111 1111 //此处取与的目的是为了保证在改变16位的同时不会影响到其他位。之后跳转到60行执行Write595(),依次写入第一个八位,0xff。写入第二个八位,0xff。写入第三个八位,0xfe。写入第四个八位,0xff 因此写入的32位数据就是0xfffeffff (16位为0)
18 Delayn(250000); //延迟,使D13发亮一段时间
19 HC595_DATA &=~(1<<17);Write595(); //类似于上面,最终得到的是1111 1111 1111 1101 1111 1111 1111 1111 写入的32位数据时0xfffdffff (17位为0)20 Delayn(250000); //延迟,使D12发亮一段时间
21 HC595_DATA &=~(1<<18);Write595(); //类似于上面,最终得到的是1111 1111 1111 1011 1111 1111 1111 1111 写入的32位数据时0xfffbffff (18位为0)
22 Delayn(250000); //延迟,使D12发亮一段时间
23 HC595_DATA &=~(1<<19);Write595();//类似于上面,最终得到的是1111 1111 1111 0111 1111 1111 1111 1111 写入的32位数据时0xfff7ffff (19位为0)
24 Delayn(250000); //延迟,使D10发亮一段时间
25 HC595_DATA |=(1<<16);Write595();
26 Delayn(250000); //D13灭
27 HC595_DATA |=(1<<17);Write595();
28 Delayn(250000); //D12灭
29 HC595_DATA |=(1<<18);Write595();
30 Delayn(250000); //D11灭
31 HC595_DATA |=(1<<19);Write595();
32 Delayn(250000); //D10灭
33 }
34}
35//初始化595接口
36void HC595_Init(void) //初始化IO口
37{
38 IO0DIR |= MOSI|RCK; //此处可以换一种写法IO0DIR |= (1<<6)|(1<<7),方向寄存器设置成输出
39 IO1DIR |= SCLK; //方向寄存器设置成输出
40 IO1CLR |= SCLK;
41 // IO0DIR |= RCK; (可以不要)
42 HC595_DATA = 0xFFFFFFFF; Write595(); //HC595_DATA = 0xFFFFFFFF的作用是置595所有的端口为高电平,使所有的发光二级管熄灭
43}
44//写字节(此处的功能不是很懂,希望有知道的朋友可以指点!)
45void WriteByte(unsigned char data) //unsigned char data是一个入口函数
46{
47 unsigned char i;
48 //IO0CLR = RCK; (可以不要,62已经声明过了)
49 for(i=0;i<8;i++)
50 {
51 if(data&0x01) IO0SET=MOSI;
52 else IO0CLR=MOSI;
53 IO1SET=SCLK; //时钟高电平
54 data>>=1; //数据移位,把数据移到串行端口
55 IO1CLR=SCLK; //时钟低电平
56 }
57 //IO0SET = RCK; (可以不要,67已经声明过了)
58}
59//刷新595的数据
60void Write595(void) //第一步595片选,然后数据写入第一个八位(0-7),再数据写入第二个八位(8-15),第三个八位(16-23),第四个八位(24-31)
61{
62 IO0CLR = RCK; //595片选
63 WriteByte(HC595_DATA&0xff); //写入第一个八位,0xff 然后跳转到45行执行WriteByte
64 WriteByte((HC595_DATA&0xff00)>>8);//写入第二个八位,0xff 然后跳转到45行执行WriteByte
65 WriteByte((HC595_DATA&0xff0000)>>16); //写入第三个八位,0xfe 然后跳转到45行执行WriteByte
66 WriteByte((HC595_DATA&0xff000000)>>24);//写入第四个八位,0xff 然后跳转到45行执行WriteByte
67 IO0SET = RCK;
68}
69//延时周期数
70void Delayn(unsigned long n) //()里面不能是void,因为此处有一个入口函数unsigned long n
71{
72 while(n--);
73}