On a recent China order I bought five 16F72 PIC microcontrollers in 16-SOIC for very cheap, thinking I could find some use for them. They sat in a box for a long time. Lately I've finally got somewhat caught up with work and have a little time for electronics tinkering again, so I decided to wire one up and make sure it wasn't junk or fake.
I used the last of my dipmicro electronics PB1 boards for this project. It appears that these great little boards may have been discontinued. I liked them so much that I may just have to draw up my own and have some made.
Here's the board early on with only RA0 and RA1 wired up. I was blinking some LEDs to make sure the MCU was running. All good so far.
The 20MHz crystal is there because the 16F72 is an old PIC design. It has no internal oscillator, and its onboard peripheral selection is very limited. Not much memory either. It's quite primitive.
Later I'll take the chip off with my hot air rework and put on either a 18F2620 or a 18F27K40, or maybe one of the two "future" 28-pin chips that Microchip has in their list. All these newer chips are really impressive, and they're all pretty much pin-compatible with the old 16F72. Might have to do a little rework on the board, but mostly it'll just work. And I can remove the crystal and run the newer chips much faster with the onboard oscillator.
Starting from left the pinout is RA0-RA5, RB0-RB5 and RC0-RC7. If I change to the modern chips I'll probably move all the RB and RC wires over two pins to open up space for RA6 and RA7.
Here's the board pretty much finished, still gooped with flux. Works perfect. I'll clean it later.
Here it is running my LED display board (74HC595 driving anodes and A6276 driving cathodes).
And here it is driving a Shift1 1-wire LCD circuit with RA0 (code below).
1_w_lcd.c
(Scroll down for .h file)
#include "1_w_lcd.h"
char buff[16];
void main(void)
{
int x;
adcon1 = 0x06; //PortA all digital IO
trisa = trisc = 0x00; //PortA PortC all outs
porta.0 = 1;
lcd_init();
lcd_cls();
line1;
lcd_string("PIC 16F72 ");
while(1){
for(x=0;;x++){
itoa(x,buff,16);
line2;
lcd_string(buff);
delay_ms(250);
}
}
}
void lcd_cmd(unsigned char letter){
unsigned char d;
d = letter; //do high nybble first
d = d & 0xf0; //mask out lower nybble
d = d | 0b00001000; //set E bit (3) high and rs bit (2) low
lcd_nybble(d); //send first time
d = d & 0b11110111; //set E bit (3) low
lcd_nybble(d); //send second time
d = letter << 4; //now do low nybble
d = d & 0xf0; //mask out lower nybble
d = d | 0b00001000; //set E bit (3) high and rs bit (2) low
lcd_nybble(d); //send first time
d = d & 0b11110111; //set E bit (3) low
lcd_nybble(d); //send second time
}
void lcd_char(char letter){
unsigned char d;
d = letter; //do high nybble first
d = d & 0xf0; //mask out lower nybble
d = d | 0b00001100; //set E bit (3) high and rs bit (2) high
lcd_nybble(d); //send first time
d = d & 0b11110111; //set E bit (3) low
lcd_nybble(d); //send second time
d = letter << 4; //now do low nybble
d = d & 0xf0; //mask out lower nybble
d = d | 0b00001100; //set E bit (3) high and rs bit (2) high
lcd_nybble(d); //send first time
d = d & 0b11110111; //set E bit (3) low
lcd_nybble(d); //send second time
}
void lcd_cls()
{
line1;
lcd_string(" ");
line2;
lcd_string(" ");
}
void lcd_nybble(unsigned char nyb){
unsigned char x;
for(x=0;x<7;x++){ //clock out 7 bits
if((nyb.7 && 0x80) == 1){ //bit 7 high?
porta.0 = 0; //yes, clock out a 1
asm{ //delay 1us
nop
nop
nop
nop
}
porta.0 = 1;
delay_us(11); //delay 15us
}
else{ //bit 7 low
porta.0 = 0; //clock out a 0
delay_us(14); //delay 15us
porta.0 = 1;
delay_us(27); //delay 30us
}
nyb <<= 1; //shift next bit to bit 7 position
}
porta.0 = 0; //send 8th latch bit
delay_us(200); //delay 200us
porta.0 = 1;
delay_10us(30); //delay 300us
}
void lcd_string(char *senpoint)
{
while(*senpoint != '\0')
{
lcd_char(*senpoint);
senpoint++;
}
}
void lcd_init(void){
delay_ms(250);
lcd_nybble(0x38); //E high - RS low - send first time
lcd_nybble(0x30); //E low - RS low - send second time
delay_ms(5);
lcd_nybble(0x38); //E high - RS low - send first time
lcd_nybble(0x30); //E low - RS low - send second time1_w_lcd/E low - RS low - send second time
delay_us(160);
lcd_nybble(0x28); //E high - RS low - send first time
lcd_nybble(0x20); //E low - RS low - send second time
delay_us(160);
lcd_cmd(0x28); //set 4-bit mode and 2 lines
delay_us(160);
lcd_cmd(0x10); //cursor move & shift left
delay_us(160);
lcd_cmd(0x06); //entry mode = increment
delay_us(160);
lcd_cmd(0x0c); //display on - cursor blink off
delay_us(160);
lcd_cmd(0x01); //clear display
delay_ms(30);
}
1_w_lcd.h
#include <system.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#pragma CLOCK_FREQ 20000000
#pragma DATA _CONFIG, _WDTEN_OFF & _HS_OSC & _CP_OFF & _BOREN_OFF
#define line1 lcd_cmd(0x80);
#define line2 lcd_cmd(0xc0);
//function prototypes
void lcd_cmd(unsigned char);
void lcd_char(char);
void lcd_init(void);
void lcd_string(char *);
void lcd_cls(void);
void lcd_nybble(unsigned char);