NJU6061是一个LED的控制模块,可以通过PWM的方式对三色的LED灯进行控制,从而达到显示多种颜色。NJU6061可以控制3路PWM信号。具体的连接方式可参考NJU6061的datasheet。NJU6061可以输出2种模式:1.固定的PWM输出 2.以扫描形式输出,即是以颜色渐变的方式来改变颜色。这里只测试固定PWM输出。
本驱动所使用的RPi的GPIO与NJU6061上的连接方式为:
//gpio.c
RPi GPIO Num NJU6061 Pin
3 RSTb
21 CS
39 CLK
38 DAT
本驱动使用了之前写过的RPi的GPIO操作的库。代码如下:
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#define BCM2708_PERI_BASE 0x20000000
#define GPIO_BASE (BCM2708_PERI_BASE + 0x00200000)
#define BLOCK_SIZE (4*1024)
#define INPUT 0
#define OUTPUT 1
#define LOW 0
#define HIGH 1
static volatile uint32_t *gpio ;
static uint8_t gpioToGPSET [] =
{
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
} ;
// gpioToGPCLR:
// (Word) offset to the GPIO Clear registers for each GPIO pin
static uint8_t gpioToGPCLR [] =
{
10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
} ;
// gpioToGPFSEL:
// Map a BCM_GPIO pin to it's Function Selection
// control port. (GPFSEL 0-5)
// Groups of 10 - 3 bits per Function - 30 bits per port
static uint8_t gpioToGPFSEL [] =
{
0,0,0,0,0,0,0,0,0,0,
1,1,1,1,1,1,1,1,1,1,
2,2,2,2,2,2,2,2,2,2,
3,3,3,3,3,3,3,3,3,3,
4,4,4,4,4,4,4,4,4,4,
5,5,5,5,5,5,5,5,5,5,
} ;
// gpioToShift
// Define the shift up for the 3 bits per pin in each GPFSEL port
static uint8_t gpioToShift [] =
{
0,3,6,9,12,15,18,21,24,27,
0,3,6,9,12,15,18,21,24,27,
0,3,6,9,12,15,18,21,24,27,
0,3,6,9,12,15,18,21,24,27,
0,3,6,9,12,15,18,21,24,27,
} ;
int GPIOSetup()
{
int fd = -1;
if ((fd = open ("/dev/mem", O_RDWR | O_SYNC) ) < 0)
{
printf ("wiringPiSetup: Unable to open /dev/mem: %s\n", strerror (errno)) ;
return 0;
}
// GPIO:
gpio = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_BASE) ;
if ((int32_t)gpio == -1)
{
printf("wiringPiSetup: mmap (GPIO) failed: %s\n", strerror (errno)) ;
return 0;
}
return 1;
}
int GPIOSetPinMode(int nPin, int mode)
{
int fSel = 0, shift = 0;
fSel = gpioToGPFSEL [nPin] ;
shift = gpioToShift [nPin] ;
#if 0
if (mode == INPUT)
*(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) ; // Sets bits to zero = input
else if (mode == OUTPUT)
*(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) | (1 << shift) ;
#else
//printf("function sel register = %p\n",gpio + fSel);
*(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) | (mode << shift) ;
#endif
return 0;
}
int GPIOGetPinMode(int nPin)
{
int mode = 0;
int fSel = 0, shift = 0;
fSel = gpioToGPFSEL [nPin] ;
shift = gpioToShift [nPin] ;
//printf("function sel register = %p\n",gpio + fSel);
return ((*(gpio + fSel))&(7<<shift))>>shift;
}
int GPIOSetPin(int nPin, int value)
{
if (value == LOW)
*(gpio + gpioToGPCLR [nPin]) = 1 << (nPin & 31) ;
else
*(gpio + gpioToGPSET [nPin]) = 1 << (nPin & 31) ;
}
//gpio.h
#ifndef RPi_GPIO_H__
#define RPi_GPIO_H__
#ifdef __cplusplus
extern "C" {
#endif
int GPIOSetup();
int GPIOSetPinMode(int nPin, int mode);
int GPIOSetPin(int nPin, int value);
#ifdef __cplusplus
}
#endif
#endif
测试的代码如下:
其中有两种模式:1.三种颜色LED同时发光,这时显示的是白光。2.分别测试三种RGB色及通过改变PWM的占空比来调节其明暗,具体步骤请参考代码。
//ledtest.c
#include "gpio.h"
#include <sys/time.h>
#define INPUT 0
#define OUTPUT 1
#define LOW 0
#define HIGH 1
#define CS 21
#define RSTb 3
#define CLK 39
#define DAT 38
#define RED 0x60
#define GREEN 0x70
#define BLUE 0x80
void delay (unsigned int howLong)
{
struct timespec sleeper, dummy ;
sleeper.tv_sec = (time_t)(howLong / 1000) ;
sleeper.tv_nsec = (long)(howLong % 1000) * 1000000 ;
nanosleep (&sleeper, &dummy) ;
}
void initialize()
{
GPIOSetup();
GPIOSetPinMode(RSTb,OUTPUT);
GPIOSetPinMode(CS,OUTPUT);
GPIOSetPinMode(CLK,OUTPUT);
GPIOSetPinMode(DAT,OUTPUT);
//hardware reset
GPIOSetPin (RSTb, LOW);
delay(10);
GPIOSetPin (RSTb, HIGH);
delay(1);
GPIOSetPin (CS, LOW);
GPIOSetPin(DAT,HIGH);
GPIOSetPin(CLK,HIGH);
}
void writeData(unsigned char cData)
{
unsigned char tmp = cData;
int i = 0;
GPIOSetPin (CS, LOW);
delay(1);
GPIOSetPin (CS, HIGH);
delay(1);
// printf("dat = ");
for(i = 7; i >=0; i--)
{
GPIOSetPin (CLK,LOW);
delay(1);
GPIOSetPin(DAT,((cData&(1<<i))==(1<<i))?HIGH:LOW);
// printf("%d ",((cData&(1<<i))==(1<<i))?HIGH:LOW);
delay(1);
GPIOSetPin (CLK,HIGH);
delay(1);
}
// printf("\n");
GPIOSetPin (CS, LOW);
}
int main(int argc, char** argv)
{
int mode = 0;
GPIOSetup();
initialize();
writeData(0x11); //frequency set
writeData(0x20); //disable sweep fucntion
if (argc !=2)
printf("Usage: ledtest mode.\n\tmode = 0 single pwm test mode \n\tmode=1 automatic pwm mode");
mode = atoi(argv[1]);
printf("mode = %d\n",mode);
if(mode == 0)
{
//display white color
writeData(BLUE|0xf); //set PWM data = 1011 duty cycle 59/128 for LED1 Blue
writeData(GREEN|0xf); //LED2 Green
writeData(RED|0xf); //LED3 Red
printf("press enter to continue.\n");
getchar();
}
else if(mode == 1)
{
for(;;)
{
int i = 0;
int nBrightness = 0;
unsigned int mSec = 1000;
for(i = 3; i >=0; i--)
{
//printf("0x80&(4*i) = 0x%x\n",0x80|(1<<i));
nBrightness = (1<<i);
printf("brightness = %d%%\n",100*(i+1)/4);
printf("Red.\n");
writeData(BLUE); //LED1 Blue
writeData(GREEN); //LED2 Green
writeData(RED|nBrightness); //LED3 Red
delay(mSec);
printf("Green.\n");
writeData(BLUE); //LED1 Blue
writeData(GREEN|nBrightness); //LED2 Green
writeData(RED); //LED3 Red
delay(mSec);
printf("Blue.\n");
writeData(BLUE|nBrightness); //LED1 Blue
writeData(GREEN); //LED2 Green
writeData(RED); //LED3 Red
delay(mSec);
printf("Red+Green.\n");
writeData(BLUE); //LED1 Blue
writeData(GREEN|nBrightness); //LED2 Green
writeData(RED|nBrightness); //LED3 Red
delay(mSec);
printf("Red+Blue.\n");
writeData(BLUE|nBrightness); //LED1 Blue
writeData(GREEN); //LED2 Green
writeData(RED|nBrightness); //LED3 Red
delay(mSec);
printf("Blue+Green.\n");
writeData(BLUE|nBrightness); //LED1 Blue
writeData(GREEN|nBrightness); //LED2 Green
writeData(RED); //LED3 Red
delay(mSec);
printf("Red+Green+Blue.\n");
writeData(BLUE|nBrightness); //LED1 Blue
writeData(GREEN|nBrightness); //LED2 Green
writeData(RED|nBrightness); //LED3 Red
delay(mSec);
printf("press enter to change brightness.\n");
getchar();
}
}
}
return 0;
}