入门STC51单片机--搭建开发环境,新建工程并点亮WS8212驱动的雪花灯
新年将至,一个漂亮的雪花灯可以增添新的气氛,带来冬日的氛围。本次分享将以这个基于STC公司的51单片机控制的雪花灯为例,讲一讲如何搭建51单片机开发环境,新建工程并点亮这个雪花灯。
标签
嵌入式系统
Robobachelor
更新2020-12-28
3172

新年将至,一个漂亮的雪花灯可以增添新的气氛,带来冬日的氛围。本次分享将以这个基于STC公司的51单片机控制的雪花灯为例,讲一讲如何零基础入门嵌入式,搭建51单片机开发环境,新建工程并点亮这个雪花灯。

开发环境的搭建

安装Keil

首先安装Keil软件,一个广泛使用的嵌入式开发工具,其中整合了代码编辑器,C51编译器及调试器为一体。下载该软件时,注意选择C51版本。不同的版本包含了不同的交叉编译工具,比如ARM版可以用来编译ARM架构的一些芯片,比如STM32,而我们的51单片机需要用C51编译器来编译。官网下载地址如下:

https://www.keil.com/download/product/

FiPNTKlj5sTj5OdhbmQiZkFcqLgM

安装完成后,需要购买软件的许可或通过其它的手段来激活软件,否则试用版只能编译较小的程序。

下载STC-ISP下载编程烧录软件

说是烧录软件,实际上说它是STC单片机的万能工具包也不为过。下面的很多步骤都会用到它。下载地址在STC公司它魔性的官网上:

http://www.stcmcudata.com/

Fp_rXXZ1_qa6vB09QHXwZ7ohobkQ

打开程序,可以看到从芯片选型,头文件,程序样例,到下载工具,各种常用功能整合到一起,给开发者节省了很多资料的时间。

Funkdqg0QHzvqJGmDUB9iYs_oSdC

向Keil中导入STC芯片的型号库和头文件库

为了能使用keil新建一个STC单片机的工程,需要选择单片机的型号来新建。而Keil软件内自带的芯片中并没有STC芯片的型号库。下面的操作将同时导入STC所有单片机芯片的型号库和头文件库,方便从keil新建工程。

打开STC-ISP软件,找到“Keil仿真设置”一栏,点击图中的按钮并根据提示选择Keil对应的安装路径即可。

FgRsADU-qOiWb3d22-aF6o4DPsyq

新建工程

从原理图可知,我们的单片机具体型号为STC15W204S。它只有8个引脚,256字节的内存,不过控制我们的雪花灯还是基本够用。在Keil的新建工程(New Project)对话框中,选择我们的芯片型号。

注意在选择芯片前,需要先在下拉框中切换到STC MCU Database。之后去找具体的芯片型号即可。

FhxSO0jCy5NLkPQ_ZAwnqpU_FA8a

选择好后,Keil会询问是否要将STARTUP.A51这个启动文件添加到工程中,回答是即可。

此时我们的工程已经新建完成,并且包含项目的第一个代码文件,也就是51单片机通用的启动文件STARTUP.A51。这是一个汇编代码,当程序编译时工程中所有的C和汇编代码都会被编译为机器指令。

添加代码文件

在Keil左侧的项目管理器中添加代码文件。在这里可以新建代码分组,在每个分组上右击可以选择新建文件,双击可以添加源代码文件。此处仅添加源文件即可,添加到此处的源代码才会被编译到生成文件中。头文件无需在此添加。

根据项目的需要,我们可以添加以下三个源文件以及对应的头文件。新建的文件为空文件,接下来需要我们来编写内容。

main.c
delay.c/delay.h
ws2812.c/ws2812.h

实现WS2812 LED驱动芯片发送功能

RGB颜色表示方法

雪花板上面的LED灯可以发出的颜色,可以用三个参数来表示:R, G, B,范围为0-255。分别对应WS2812模块中内置的红色、绿色、蓝色三颗发光二极管的亮度。红,绿,蓝为显示的三原色,将三种颜色的光的亮度按照不同的大小叠加起来,就可以得到五彩斑斓的颜色。例如(255,255,255)为白色,(100,100,100)就是暗一些的白色,(255,255,0)则为橙色,因为它是红色和绿色的叠加。

WS2812的单总线数据传输协议

每个WS2812上面有红绿蓝三种颜色的LED灯,需要按照绿-红-蓝的顺序接受到24字节的数据才能正常工作。其中每个颜色的数据长度为8位,因此数据范围为0-255.

WS2812的妙处在于,用单片机向WS2812发送数据,只需要一根线,而不像SPI等协议需要很多根线。而且当有多个WS2812时,不需要从单片机向所有的模块都连一根线,而是可以将前一个WS2812模块的发送端连接到下一个的接收端,这样串起来连接。

Fh6NXO04OXzisGOojmnQejH19TC9

https://cdn-shop.adafruit.com/datasheets/WS2812.pdf

通过查阅WS2812的数据手册,可以了解到该模块的通信方式。该芯片可以自动转发,也就是说从单片机可以一次发送多个灯的数据,第一个灯可以吃掉前24位的数据,并将剩余的数据发送给后面的灯。对于后面的灯,它们同样是吃掉它们得到的数据的前24位,用于控制自己的亮度,之后把后面的数据丢到后面的灯。按照这样的协议,单片机可以按照灯的总线连接顺序一次按顺序发送所有WS2812的数据。

数据手册还告诉我们,对于每24bit的数据,绿色在前,接着是红色,蓝色。对于每个颜色,先发高位,后发低位。

FmFp1fNPdxVi5GF6jMwdQzLRHAzM

那么如何发送每一位的数据是1还是0呢?查阅数据手册,总线上的电平每跳变一次,表示发送了一位数据。而按照规定的时间保持高电平和低电平,就可以表示要发送的是0还是1。保持较长时间的低电平,表示发送的是RESET Code。

实现WS2812发送一位数据

回到我们的STC15W单片机。这个单片机的速率并不快,内部时钟最高也通常只能达到33MHz左右。如何用这个单片机实现数百微秒的延时呢?__nop_()语句可以实现让单片机的CPU执行一个空指令,什么也不做但是可以延时一个时钟周期。通过使用逻辑分析仪,我看可以测试出大约多少个nop()可以达到数据手册规定的延时时长。

我们把单片机的内部时钟调节为33MHz。之后可以编写这样的代码,来实现WS2812发送低位或发送高位。

#define WS2812_Send_Bit_High {\
	DI=1;\
	_nop_();\
	_nop_();\
	_nop_();\
	_nop_();\
	_nop_();\
	_nop_();\
	_nop_();\
	_nop_();\
	_nop_();\
	_nop_();\
	_nop_();\
	_nop_();\
	_nop_();\
	_nop_();\
	_nop_();\
	_nop_();\
	_nop_();\
	_nop_();\
	_nop_();\
	_nop_();\
	DI=0;\
	_nop_();\
	_nop_();\
	_nop_();\
	_nop_();\
	_nop_();\
	_nop_();\
	_nop_();\
	_nop_();\
	_nop_();\
	_nop_();\
	_nop_();\
	_nop_();\
	_nop_();\
	_nop_();\
	_nop_();\
}
	
#define WS2812_Send_Bit_Low {\
	DI=1;\
	_nop_();\
	_nop_();\
	_nop_();\
	_nop_();\
	_nop_();\
	_nop_();\
	_nop_();\
	DI=0;\
	_nop_();\
	_nop_();\
	_nop_();\
	_nop_();\
	_nop_();\
	_nop_();\
	_nop_();\
	_nop_();\
	_nop_();\
	_nop_();\
	_nop_();\
	_nop_();\
	_nop_();\
	_nop_();\
	_nop_();\
	_nop_();\
	_nop_();\
	_nop_();\
	_nop_();\
}

实现WS2812发送所有数据

下面的函数用来发送多个字节的WS2812数据,例如发送三个字节可以控制第一个WS2812模块的颜色,发送n*3个字节则可以控制单片机后面的n个灯。

buf为要发送的数据的指针,byte_length为数据长度,单位为字节。

void WS2812_Send(uint8_t *buf, uint8_t byte_length){
	uint8_t i, j;
	for(i = 0; i < byte_length; ++i){
		for(j = 0; j < 8; ++j){
			if(buf[i] & (0x80 >> j)){
				WS2812_Send_Bit_High;
			} else{
				WS2812_Send_Bit_Low;
			}
		}
	}
}

编写一个测试程序

接下来,将使用上面写好的WS2812发送功能,来编写主函数main.c文件。

LED待发送数据结构

定义下面的联合体,使其既可以按照要发送的数据的顺序存储,又可以按照每个灯的r,g,b颜色的方式来访问。

union{
	uint8_t buf[LED_NUM*3];
	struct{
		uint8_t g, r, b;
	}u[LED_NUM];
}LED;

延时函数

粗略的延时可以通过固定次数的循环来实现。STC-ISP中的软件延时计算器可以为我们生成一个粗略的延时函数:

Fouf6uY7UUUmv5HJifro_pJUduFO

完整的main.c

最后,可以编写如下代码来测试我们的程序是否正常工作。雪花灯将像封面效果一样点亮,并一秒钟交换一次颜色。

#include "ws2812.h"
#include "delay.h"

union{
	uint8_t buf[LED_NUM*3];
	struct{
		uint8_t g, r, b;
	}u[LED_NUM];
}LED;
	
void  main()
{
	LED.u[36].r = LED.u[36].g = LED.u[36].b = 30;
	while(1){
		LED.u[15].r = LED.u[16].g = LED.u[17].b = 0;
		LED.u[16].r = LED.u[17].g = LED.u[15].b = 60;
		WS2812_Send(LED.buf, LED_NUM*3);
		Delay100Ms(10);
		
		LED.u[16].r = LED.u[17].g = LED.u[15].b = 0;
		LED.u[15].r = LED.u[16].g = LED.u[17].b = 60;
		WS2812_Send(LED.buf, LED_NUM*3);
		Delay100Ms(10);
	}
}
团队介绍
团队成员
王景祎
西交利物浦大学 数字媒体技术专业大二学生 现担任西浦GMaster机器人战队副队长,电控组组长
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2023 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号