Tag Archive for Microchip

Using Digole 12864ZW LCD with PIC18F

PIC18F interface with digole 12864ZW PIC18Fとグラフィック ディスプレイのインターフェイス facebooktwittergoogle_plusredditpinterestlinkedinmailby feather

Hello, こんにちは,

私の日本語があまり上手くありませんが許して下さい.

PIC18Fとグラフィック ディスプレイのインターフェイス

Digole 12864ZW is a 128×64 pixels graphic LCD that can be found at attractive prices and this is why it started appearing in projects across the web. It is based on ST7920 chip which is not so well known and to me it wasn’t the easiest to work with.

私は、グラフィックモードでDigole12864ZWを使用する方法について記述します。C18コンパイラとPIC18F4620を使用しています。

ここで、LCDのデータシートです。

The documentation for this display can be found here. You can find a couple of examples on how to use this display and some attempts on making a library and most of this information is for interfacing with arduino. For PIC interfacing i couldn’t find much info.

The module has a 20 pin connection, each described below. Vout i havent used and left it unconnected. For contrast you can use V0 (pin 3) by connecting it to Vdd through a 10k variable resistor. However to get it to work you will need to enable jumper J1 from the back of the module as in figure 1.

Pin # Function
1 Vss
2 Vdd
3 V0
4 RS
5 RW
6 EN
7 DB0
8 DB1
9 DB2
10 DB3
11 DB4
12 DB5
13 DB6
14 DB7
15 PSB
16 NC
17 RST
18 VOUT
19 BLA
20 BLK
Digole 12864ZW PIC18F contrast

Figure 1

As per the datasheet the display can be used in many ways and this is a strong feature. I used it the traditional way 8 bits parallel. For this, PSB pin must be connected to Vdd, i also connected RST pin to Vdd as i will reset the display in software. The rest of the connections are the same as with any 16×2 alphanumeric displays.

コントラストが機能するためには、J1を有効にする必要があります。写真1を参照してください。

Microchip XLCD library is a great starting point to using the Digole 12864ZW with a PIC microcontroller. I used Application Maestro to set up the library. As mentioned we will use 8 bits interface in delay mode. Set the ports and pins and the rest doesn’t really matter.

アプリケーションマエストロとのXLCDファイルの設定。

Application Maestro XLCD

Figure 2

Once done pressing Ctrl+G will generate the library files to be included in your project. You will need the XLCD.h, XLCD.c and XLCD.def. Now this Digole display can run in text mode with this library with major issues.To get to each line though you will need to go to specific addresses.

To use the LCD in graphic mode we will need to change the XLCDinit function in XLCD.c file. You can comment the one you have now and then copy paste the function below:

以下のコードでXLCD.cファイルにXLCDInitコードを交換してください。

void XLCDInit(void)
{
_vXLCDreg=1;

XLCD_DATAPORT_TRIS  = 0x00; 
XLCD_DATAPORT = 0;
XLCD_RSPIN_TRIS =0;                         
XLCD_ENPIN_TRIS =0;
XLCD_RWPIN_TRIS =0;
XLCD_RSPIN  =0;                             
XLCD_ENPIN  =0;
XLCD_RWPIN=0;                               
XLCDDelay15ms(); 
XLCD_DATAPORT   = 0b00110000;   
XLCDDelay4ms();
XLCD_DATAPORT   = 0b00110000;   
XLCDDelay4ms(); 
XLCDCommand(0x0C); 
XLCDDelaylcd();   
XLCDCommand(0x01); 
XLCDDelay15ms();  
XLCDCommand(0x06); 
XLCDDelaylcd();
XLCDCommand(0x34); 
XLCDDelay15ms();    
XLCDCommand(0x36); 
XLCDDelay15ms(); 

_vXLCDreg=0;
return;
}

The other two functions we will use from the XLCD library are XLCDCommand and XLCDPut, which are used to pass a command to the display and a value respectively. Using these functions you don’t have to worry about controlling RS , RW and EN.

After calling the XLCDinit() function in main() you have now setup the display in graphic mode. To start drawing you need first 2 XLCDCommand instructions that set the pixel address and then 2 XLCDPut instructions to draw the pixels.

In figure 3 you can see the address map of Digole 12864ZW in the operating mode described above. It can be observed the horizontally you cannot address pixels individually but in groups of 16 and values you can write in groups of 8. The 1st byte represents the byte in the first XLCDPut instruction and the 2nd byte the value in the 2nd instruction. You cannot make 1 byte to start at the middle of the address location. We have 8 addresses of 16 pixels each horizontally 8×16=128 pixels and 64 lines =>128×64 resolution.

Digole12864ZWグラフィックアドレスマップ

Digole 12864 Address Map アドレスマップ

Figure 3

//Example:

/* In figure 3 there are 4 red pixels. To set the pixel we need the following instructions:

Note that we are in region where x=0 => */

XLCDCommand(0b10010010); // 1st instruction

XLCDCommand(0b10000001); // 2nd instruction

XLCDPut(0b00110001); // 1st byte, red pixels are 1 in value

XLCDPut(0b00000010); // 2nd byte, red pixel is 1 in value

/* As you can see the position of the pixels in the two bytes are the positions of 1 in the XLCDPut values */

So to draw a horizontal line of a specific length you will need to take in consideration the fact that you will always set all 16 bits in one of the 8 horizontal addresses.

//Example: Draw line from pixel 41 to end of screen at line 10

/* x = 41/16 = 2; x_r = 41%16 = 9; This means we will start the line from the 2nd byte of horizontal address 010. y = 10 => H_ADDRESS = 0b10000010 */

// lets draw the first part of line 

int index_x, index_y, i;

index_y = 10;

index_x = 41/16;

XLCDCommand(0x80 | index_y); // V_ADDRESS

XLCDCommand(0x80 | index_x); //H_ADDRESS

XLCDPut(0x00); //1st byte is zero

XLCDPut(0x7F); //x_r%8 = 1 => values is 0xFF >> 1 meaning 0b01111111

//now draw to end of screen

for(i=3;i<8;i++)

{

XLCDCommand(0x80 | index_y);

XLCDCommand(0x80 | i);

XLCDPut(0xFF);

XLCDPut(0xFF);

}

Another good reason to use graphic mode is to create your own fonts for text. In its own text mode the display’s characters are very large and can only fit 4 lines. I have created my own set of characters of 7×7 pixels. I have used the fact that each horizontal address has two bytes so that i can fit a character’s width in one byte and leave 1 empty pixel as space. In Figure 4 you can see the W character and its pixel representation. It uses 1 byte on 7 lines so 7 bytes.

 

Character map DIgole 12864 display

Figure 4

This way each character can be represented as a vector of 7 bytes:

int chW[7]={ 146, 146, 146, 146, 146, 170, 68 };

To display a string i separate each character and based on its value i fill a matrix of [7][8] dimension representing a text line on the display. To use it easily the matrix is declared as follows:

union writebyte
{
struct
{
char LowByte;
char HighByte;
};

}linebytes[7][8];

This way you can easily call XLCDPut functions with LowByte or HighByte as arguments. Here is the case for W within the character switch function:

case ‘w':
{
for(j=0;j<7;j++)
{
if(k%2 == 0)
{
linebytes[j][k/2].LowByte=chW[j];
}
else
{
linebytes[j][k/2].HighByte=chW[j];
}
}
}break;

where j is the line number and k is the character number. Below you can see how it looks like:

 PIC18Fとグラフィック ディスプレイのインターフェイス

 PIC18Fとグラフィック ディスプレイのインターフェイス interfacing PIC18F with Digole 12864ZW

 PIC18Fとグラフィック ディスプレイのインターフェイス interfacing PIC18F with Digole 12864ZW

 

In the zip archive below you can find the font.h containing definitions for characters seen above and an example code for PIC18F4620 that displays the message stored in msg[] variable.

I will add more characters and functions with time but i hope this was helpful for anyone trying to interface Digole 12864ZW LCD to a PIC18F.

フォントの収集とPIC18F4620用のサンプル·コード

Digole 12864W sample code for PIC18F4620

Thank you for visiting,

ご覧いただきありがとうございます。

Implementing Software SPI for PIC 2 PIC Communication

facebooktwittergoogle_plusredditpinterestlinkedinmailby feather

Hello,

In one of my projects i had to transmit some data between two PIC microcontrollers. The data represented some sensor values and it was important to know which value corresponded to which sensor.

This can be tricky if you don’t have free peripherals so i will present a way to implement SPI style communication by bit-banging any pin/port available. As with most SPI you will need 4 wires representing Clock, MISO (Master In Slave Out), MOSI (Master Out Slave In) and CS (Chip Select or Slave Select or Data Enable….).

Scenario is like this PIC1 MCU converts analog value of a few sensors with a 16bit resolution and then sends the data to PIC2 MCU for further processing. PIC2 needs to know that the data that was just received corresponds to a certain sensor. When can achieve this simply by letting PIC2 make a data request to PIC1.

E.g.

PIC2: [SEND DATA OF SENSOR 3]—————->:PIC1

PIC1:[SENDING SENOR 3 DATA]——————>:PIC2

PIC2: [SEND DATA OF SENSOR 7]—————->:PIC1

PIC1:[SENDING SENOR 7 DATA]——————>:PIC2

This way PIC2 will always associate the received data with the right sensor. It seems natural that PIC2 will be the SPI Master and PIC1 will be the slave. The Master is the one initiating the communication by first setting CS line to logic low and then starting the clock. It will then send the sensor address to the slave and receive the value from the slave. Once value was read it will stop the clock and set CS to logic high.

I assigned each sensor an address, 8 bit is enough allowing basically for 256 sensors. The received data is 16 bits long.

1. SPI MASTER program

/* I will use delay functions which you will need to define according to your compiler

and your Fcy settings. */

//Defining Signal Lines, replace “x” chars with your port/pin numbers

#define DCLK PORTxbits.Rxx
#define DIN PORTxbits.Rxx //MISO
#define DOUT PORTxbits.Rxx //MOSI
#define CS PORTxbits.Rxx

//Function to configure the data direction

//If you add these functions after main() remember to add prototype before main()

void Init_MSPI(void)

{

TRISxbits.TRISxx = 0; // clock
TRISxbits.TRISxx = 1; // DIN
TRISxbits.TRISxx = 0; // DOUT
TRISxbits.TRISxx = 0; // CS

//look in your MCU h file to get the actual TRIS struct parameters

CS=1;
DCLK=1;

}

UINT16 Get_Value_SSPI(char ADDRESS)

{

char temp; //used to serialize data

UINT16 in=0x0000; //will hold received 16bit data, initialize with 0

CS=0;

__delay_us(50);

//CS Line set to logic low

//begin serializing ADDRESS and sending it via DOUT from MSB to LSB

for(i=0;i<8;i++)
{
temp=ADDRESS&0x80; //Keep the MSB, ignore the rest of the bits
if(temp) // if MSB is 1 put 1 on DOUT and cycle clock 
{
DOUT = 1;
DCLK = 0;
__delay_us(50);
DCLK = 1;
__delay_us(50);
}
else //if MSB is 0 put 0 on DOUT and cycle clock
{
DOUT = 0;
DCLK = 0;
__delay_us(50);
DCLK = 1;
__delay_us(50);
}
ADDRESS <<=1; // Shift data to the right to get the next bit in MSB position
}

//cycle clock again, prepare to receive
DCLK = 0;
__delay_us(50);
DCLK = 1;
__delay_us(50);

//receiving the data
for(i=0;i<16;i++)
{
DCLK = 0; //activate clock
if(DIN) // if on DIN line we have 1 we put 1 in LSB position of “in” variable
in|=0x0001;
__delay_us(50);
DCLK = 1;
__delay_us(50);

//if DIN 0 leave variable unchanged, cycle clock
in<<=1; // shift LSB to right and prepare to receive the next bit
}

 //reception of last bit needs to be out of for loop so it wont get shifted to the right

if(DIN)
in|=0x0001;
DCLK = 0;
__delay_us(50);
DCLK = 1;
__delay_us(50);

//cycle clock and close communication by putting CS line to logic high

CS=1;
__delay_us(50);

}

// to call the function in main

UINT16 Sensor_Value;

Sensor_Value = Get_Value_SSPI(ADDRESS);

2. SPI Slave Program

//Defining Signal Lines, replace “x” chars with your port/pin numbers

#define DCLK PORTxbits.Rxx
#define DIN PORTxbits.Rxx //MISO
#define DOUT PORTxbits.Rxx //MOSI
#define CS PORTxbits.Rxx

//Function to configure the data direction

//If you add these functions after main() remember to add prototype before main()

void Init_SSPI(void)

{

TRISxbits.TRISxx = 1; // clock
TRISxbits.TRISxx = 1; // DIN
TRISxbits.TRISxx = 0; // DOUT
TRISxbits.TRISxx = 1; // CS

//notice clock and CS are inputs on slave MCU

}

void Send_Value_MSPI(void)

{

char address=0x00; //variable to hold sensor address

UINT16 out,temp; //out holds the sensor value, temp used to serialize data

while(!CS);
while(CS);

//wait for CS line to cycle to logic low

//this prevents the Slave to start its routine in the middle of communication

//start receiving Master data on DIN
for(i=0;i<8;i++)
{
if(DIN) //if DIN is 1 put 1 in data as LSB if 0 leave data unchanged
data|=0x01;
data<<=1; //shift LSB to the right, wait for clock and prepare for new bit
while(!DCLK);
while(DCLK);
}
if(DIN)//last bit must be out of for loop to prevent shifting it to the right
data|=0x01;

/*wait 2 clock periods in here you should get the value corresponding to the received address */
while(!DCLK);
while(DCLK);
while(!DCLK);
while(DCLK);

// serialize the value and send it bit by bit on DOUT

for(j=0;j<16;j++)
{
temp = out&0x8000;// keep MSB and ignore the res
if(temp) //toggle DOUT depending on MSB
DOUT=1;
else
DOUT=0;
out<<=1;//shift data to the right prepare next bit as MSB and wait for clock
while(!DCLK);
while(DCLK);
}
DOUT=0; // once all bits are sent put DOUT to 0 and wait final clock
while(DCLK);
while(!DCLK);

}

Ran the software on 2 PIC24FJ128GA010 devices and below you can see the signals. Remember DOUT form Master goes to DIN on Slave and DIN from Master Goes to DOUT on Slave. From top to bottom 1st signal = Clock, 2nd signal = Master DOUT, 3rd signal = Master DIN, 4th signal = CS

ADDRESS = 0xC2 Sensor_Value = 0xF10F

SPI Communication PIC

 

 

to see if each PIC MCU will interpret the data correctly i added a verification point on both programs by making a pin go high if the data is verified. Below you can see the signals.

SPI Communication PIC

showing control output and data lines

SPI Communication PIC

Showing control output with Clock and CS lines

 

You can change delay values in the Master program for faster or slower transmission, just make sure you have the same value everywhere. The beauty part is that you can use it with any ports/pins and not worrying about your peripherals.

Thank you for visiting.

Wolfson WM8510

facebooktwittergoogle_plusredditpinterestlinkedinmailby feather

I started recently to look at Wolfson’s WM8510 audio codec. It is a mono device featuring 24 bit ADC and DAC running up to 48kHz sampling rate. It has some pre-defined DSP functions, filters, automatic level control ALC, programable gain and input selection.

Also it has a briged small power amplifier that can be used as a balanced output although it will need some decoupling caps. It is a nice chip and I become interested in it since it was on the dsPIC Digital Signal Controller Starter Kit from Microchip.

Microchip provides in their demo files a driver for this codec however they only define functions that set a low sampling rate of 8kHz and 16kHz.

I will explore in the next days the capabilities of this codec driving it at 48kHz sampling rate and i will show you how to modify the Microchip driver.

Wm8510G

Temperature Effect Analysis Tool

facebooktwittergoogle_plusredditpinterestlinkedinmailby feather

 

こんにちは,

私は、スピーカーに対する温度の影響を監視するために開発したツールをご紹介したいと思います。これは、Microchip社のPIC18F4550マイクロコントローラーを中心に構築されており、
USBポート経由でPCに接続されています。デスクトップアプリケーションは、私のパートナーがC#でプログラムをしました。

 

Hello everyone,

I want to present a tool I developed for monitoring temperature effects on loudspeaker performance. It is built around PIC18F4550 microcontroller from Microchip and it connects to a PC via USB port. Desktop application was programmed in C# by one of my partners.

DSC03402

The tool uses a reference resistor to calculate the changes in field coil and voice coil resistance. The voltage captured is fed into the 10 bit ADC on the microcontroller. It is also equipped with a LM35 temperature sensor in order to calculate the voice coil’s temperature coefficient. This parameter can be used to predict power compression.

DSC03388 DSC03389 DSC03390

 

The Desktop application will display graphs showing the time variation of four parameters. Data can also be saved for further processing.

tea