PIC16C84 har fyllt 20 år (Modbus-styrt nätaggregat)

Berätta om dina pågående projekt.
void
Inlägg: 119
Blev medlem: 8 juli 2007, 11:06:50
Ort: Enköping

PIC16C84 har fyllt 20 år (Modbus-styrt nätaggregat)

Inlägg av void »

Det är 20 år sedan PIC16C84 lanserades och det tänkte jag fira med ett litet projekt.

2014-02-09 15.25.07.jpg
16C84:ans i korthet:
  • 1k EEPROM/FLASH
    36 bytes RAM
    1 MIPS @ 4 MHz
    En 8-bit timer
För att göra det extra mysigt har jag letat fram en tidsenlig laptop för utvecklingsmiljön:

2014-02-09 16.05.08.jpg
En Compaq LTE 5000 med 75 MHz Pentium och 24 MB RAM, och Windows 98SE. Nu kan det roliga börja.

2014-02-09 15.20.56.jpg
Pic Start Plus:en och laptopen har nästan samma beige färg, snyggt!
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
Senast redigerad av void 10 februari 2014, 10:15:43, redigerad totalt 1 gång.
Användarvisningsbild
kankki
Inlägg: 3369
Blev medlem: 2 januari 2010, 15:05:12
Ort: Nykarleby, Finland

Re: PIC16C84 har fyllt 20

Inlägg av kankki »

Den där kunde man väl programmera en gång och sen var det kört, visst? Överskrivbart minne kom väl först med F-versionen?
thomasloven
Inlägg: 96
Blev medlem: 2 februari 2011, 13:16:32
Kontakt:

Re: PIC16C84 har fyllt 20

Inlägg av thomasloven »

Jag fick tag på några 16C84 när jag började intressera mig för elektronik. De gick bra att skriva flera gånger trots att det mycket riktigt inte skulle gå.

Troligen felmärkta, eller märkta med C av bakåtkompabilitetsskäl när flashminnen hade blivit billigare än att driva två produktionslinor. Det var i alla fall min gissning.
daer
Inlägg: 368
Blev medlem: 13 juni 2008, 22:15:27
Ort: Höör och Helsingborg, Skåne

Re: PIC16C84 har fyllt 20

Inlägg av daer »

PIC16C84 var den första med EEPROM istället för EPROM.
Så dessa gick att programera flera gånger. Det var den första PIC varianten som gick att elektriskt radera.
F varianten kom mycket senare men med flash istället för EEPROM.

http://en.wikipedia.org/wiki/PIC16x84
Användarvisningsbild
Icecap
Inlägg: 26620
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: PIC16C84 har fyllt 20

Inlägg av Icecap »

Då PIC16C84 kom fram var det avgörande för den just att den inte var OTP men hade EEPROM-programminne.
void
Inlägg: 119
Blev medlem: 8 juli 2007, 11:06:50
Ort: Enköping

Re: PIC16C84 har fyllt 20

Inlägg av void »

Sådär då var MPLAB igång. Det fick bli version 5.70.40, eftersom det var den sista som hade support för 16C84.

mplab4.jpg
Riktigt "snappy" känsla trots 75 MHz och 24 MB RAM. Microchip rekommenderade minst 32 MB, men de ville nog vara på säkra sidan så att folk inte skulle bli missnöjda :) Möjligen är simulatorn mer krävande. Som C-kompilator har jag valt CC5X från Knudsen. Den är fri och jag vet sedan tidigare att den genererar kompakt kod.
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
blueint
Inlägg: 23238
Blev medlem: 4 juli 2006, 19:26:11
Kontakt:

Re: PIC16C84 har fyllt 20 år

Inlägg av blueint »

Klart den är snabb när du slipper program med en massa bloat .. :vissla:

75 MHz Pentium var väl också nära brytgränsen för att kunna köra de flesta program snabbt.
void
Inlägg: 119
Blev medlem: 8 juli 2007, 11:06:50
Ort: Enköping

Re: PIC16C84 har fyllt 20 år

Inlägg av void »

Ha ha, ja om man inte kallar radnummer i editorn för bloat...

Nu är utvecklingsmiljön på plats, och det börjar bli dags att presentera själva projektet. Jag tänkte bygga ett Modbus-styrt nätaggregat. Till nätaggregatet behöver jag en UART för kommunikationen och två PWM-kanaler, en för att styra spänning och en för strömbegränsningen. Dessutom vill jag kunna mäta aktuella värden för både ström och spänning så det behövs en ADC med två ingångar. Idén är att allt skall lösas i mjukvara, utan extra kretsar.

Modbus-paketen kommer in på serieporten och avkodas. Jag tänker mig två funktioner, med den ena skickas nya värden för de två PWM-kanalerna, och med det andra returneras de uppmätta värdena för ström och spänning. I mån av plats kan jag bygga ut med fler funktioner, några förslag?

Jag tänkte att 8-bitars upplösning får räcka för både PWM och ADC, så det blir inga superprestanda. Upplösningen för spänning blir ~100mV, och ström ~10mA.
blueint
Inlägg: 23238
Blev medlem: 4 juli 2006, 19:26:11
Kontakt:

Re: PIC16C84 har fyllt 20 år (Modbus-styrt nätaggregat)

Inlägg av blueint »

Det finns även ett operativsystem som suger kraft osv. Så det är betydigt mer än applikationen som avgör hur effektivt datormiljön fungerar.

Vad fick dig att välja modbus? jämfört med t.ex Ethernet?

För kommando uppsättningen kanske det kan vara värt att kika på: SCPI?

Bitupplösningen kanske bör ökas något? Då om man vill t.ex ladda batterier så behövs kanske 0,025 mV steg för att få en viss justeringsmarginal. 10..12 bitar kanske vore bra?
void
Inlägg: 119
Blev medlem: 8 juli 2007, 11:06:50
Ort: Enköping

Re: PIC16C84 har fyllt 20 år (Modbus-styrt nätaggregat)

Inlägg av void »

Mjaa alltså, det här blir en väldigt simpel sak, närmast som en ploj, jämfört med alla de fina konstruktioner som visas här på forumet :oops: Hela idén är att allt ska få plats i 36 byte RAM, och UART/PWM/ADC skall köras i mjukvara i samma 16C84. SCPI-protokollet är intressant, det har jag inte stött på tidigare, men även det verkar vara lite för komplicerat här. Det gäller att hålla hårt i "byten".

Jag tänkte först fixa till programmet och sedan göra hårdvaran (op-förstärkare transistorer etc). Mjukvaran vill jag göra i ett par steg, där jag testar varje steg innan jag går vidare.

Jag börjar med UART-delen. Eftersom den analoga utgången (PWM) måste snurra så stor del av tiden som möjligt och man inte vet när ett nytt kommando kommer får jag lägga seriekommunikationen i interruptrutinen.
H.O
Inlägg: 5890
Blev medlem: 19 mars 2007, 10:11:27
Ort: Ronneby

Re: PIC16C84 har fyllt 20 år (Modbus-styrt nätaggregat)

Inlägg av H.O »

Kul projekt!! Lite lagom galet men riktigt inspirerande och kul.
Ska bli intressant att se om och hur du fixar att implementera en MODBUS stack, och resten, med de tämligen begränsade resurserna. (Själv är jag kass på assembler....) Förstår att du inte ens överväger "Ethernet".....

För övrigt så är ju både SCPI och MODBUS på ett helt annat "lager" än Ethernet, det går ju t.ex att köra MODBUS över Ethernet. Samma sak med SCPI, det är ju ett "språk" som kan "sändas" och "tas emot" på många olika sätt och över många olika medier - olika saker alltså.
void
Inlägg: 119
Blev medlem: 8 juli 2007, 11:06:50
Ort: Enköping

Re: PIC16C84 har fyllt 20 år (Modbus-styrt nätaggregat)

Inlägg av void »

Tack för vänliga ord!

Ok, nu har jag gjort en testuppkoppling och knåpat ihop seriekommunikationen. Jag valde att använda timrer0 som "free running" med interrupt var 1/1200 sekund, för då kan jag använda den för att ta emot och sända tecken (dvs @1200 baud) utan att blockera processorn. Vid mottagning använder jag interruptet på RB0 för att detektera flank på startbit som synkroniserar timern.

2014-02-11 10.25.55-1.jpg
Testuppkopplingen. Har gjort små moduler med LED och RS232 för att underlätta. PICkit2 används till VCC. För att slippa lyfta ur C84:an vid varje programmering har jag gjort en ISP-kabel. Jag blinkar även 2 dioder (obligatoriskt).

build1.png
Nu har jag förbrukat 287 ord och 14 byte RAM.

terminal1.png
Jag spexade till det lite så vid bootning visas välkomstmeddelande och en prompt 8) (eeh lite nördigt kanske).

Här kommer lite kod utifall någon (mot förmodan) är nyfiken:

Kod: Markera allt

/******************************************************************************
* File: 	part1.c
* Platform:	PIC16C84, MPLAB 5.70.40/CC5X
*
* 
* Version history: 
* 2014-02-10 	1.0 	Test av bitbangad UART 
* 
*******************************************************************************/

#include "inttypes.h"					

#define FULLBIT 	58
#define HALFBIT 	152
#define TRUE  		1
#define FALSE 		0

#define DEBUG	PORTA.0 = 1; nop2(); nop2(); PORTA.0 = 0
#define DEBUG1	PORTA.1 = !PORTA.1;

enum TASKS_T {LED1, LED2};
uint8_t tasks[LED2 + 1];

typedef enum {UWAIT,RSTART,RD1,RD2,RD3,RD4,RD5,RD6,RD7,RD8,RSTOP,
				    TSTART,TD1,TD2,TD3,TD4,TD5,TD6,TD7,TD8,TSTOP,RXEMPTY=0xF0} UART_E;
struct {
	uint8_t rxbuffer;
	uint8_t txbuffer;
	UART_E 	status;
} uart;

#pragma location 0						//codepage 0
#include <INT16CXX.H>
#pragma origin 4
interrupt int_server(void) 
{
	static uint8_t tmp, rxtmp;
	int_save_registers 					// W, STATUS (and PCLATH)
	char sv_FSR = FSR;

	if (INTF && INTE) {					//edge on startbit detected
		INTF = FALSE;
		if (uart.status == UWAIT) {
			INTE = FALSE;
			TMR0 = HALFBIT;			
			uart.status = RSTART;		//run receiver
		}
	} 
	
	if (T0IF && T0IE) {
		TMR0 = FULLBIT;
		
		//UART - bitbanged receiver
		if (uart.status == UWAIT)			
			;
		else if (uart.status == RSTART) {	
			++uart.status;
			if (PORTB.0 != 0) {			//startbit expected to be low
				INTF = FALSE;
				INTE = TRUE;
				uart.status = UWAIT;
			}
		}
		else if (uart.status > RSTART && uart.status < RSTOP) {
			DEBUG;
			tmp = PORTB.0;
			tmp <<= 7;
			rxtmp >>= 1;
			rxtmp |= tmp;				//save databit
			++uart.status;	
		}
		else if (uart.status == RSTOP) {
			if (PORTB.0 == 1) 			//stopbit expected to be high
				uart.rxbuffer = rxtmp;
			else	
				uart.rxbuffer = RXEMPTY;
				
			uart.status = UWAIT;
			INTF = FALSE;
			INTE = TRUE;
		} 
		else if (uart.status == TSTART) {	//UART - bitbanged transmitter
			++uart.status;
			PORTB.1 = 0;				//make startbit
		}
		else if (uart.status > TSTART && uart.status < TSTOP) {
			++uart.status;			
			tmp = uart.txbuffer & 0x01;
			PORTB.1 = tmp;				//databit to port
			uart.txbuffer >>= 1;
		}
		else if (uart.status == TSTOP) {
			++uart.status;				
			PORTB.1 = 1;				//make stopbit
			uart.status = UWAIT;		//we are ready to send next char
		}

		//scheduler
 		for (tmp = 0; tmp < sizeof(tasks); ++tmp)
			if (tasks[tmp])
				--tasks[tmp]; 

	}
	FSR = sv_FSR;	
	int_restore_registers
	T0IF = FALSE;						//clear timerflag for next tick	
}

#include <math16.h>

/******************************************************************************
* kbhit - Tecken mottaget? 
* 
* 
******************************************************************************/
uint8_t kbhit(void) {

	if (uart.rxbuffer != RXEMPTY)
		return TRUE;
	else
		return FALSE;
}


/******************************************************************************
* putch - Skriv tecken till UART 
* 
* 
******************************************************************************/
void putch(uint8_t c) {

	while (uart.status != UWAIT)
		;
	uart.txbuffer = c;
	uart.status = TSTART;
}

/******************************************************************************
* puts - Skriv sträng till UART 
* 
* 
******************************************************************************/
void puts(const uint8_t *s) {
	uint8_t c;
	
	c = *s;
	while (c) {
		putch(c);
		s++;
		c = *s;
	}	
}

/******************************************************************************
* crlf - Gör radmatning 
* 
* 
******************************************************************************/
void crlf(void) {
	
	putch(0x0d);
	putch(0x0a);
}

/******************************************************************************
* task_led1 - blinka LED 1
*
* 
******************************************************************************/
void task_led1 (char p) {

	if (PORTA.0) {
		tasks[LED1] = 0xff - p;
		PORTA.0 = FALSE;
	} 
	else {
		tasks[LED1] = p;
		PORTA.0 = TRUE;
	}
}

/******************************************************************************
* task_led2 - blinka LED 2
*
* 
******************************************************************************/
void task_led2 (char p) {

	if (PORTA.1) {
		tasks[LED2] = 0xff - p;
		PORTA.1 = FALSE;
	} 
	else {
		tasks[LED2] = p;
		PORTA.1 = TRUE;
	}
}


/******************************************************************************
* main - 
*
* 
******************************************************************************/
void main(void) {
	uint8_t led1_speed;

	TRISA = 0b0000.0000;
	TRISB = 0b0000.0001;				
	OPTION_REG = 0b1100.0001;
	
	INTEDG = FALSE;
	INTF = FALSE;	
	INTE = TRUE;    							
	TMR0 = FULLBIT;
	T0IF = FALSE;
	T0IE = TRUE;
	RBIE = FALSE;
	RBIF = FALSE;	
	PORTB.1 = 1;
	GIE = TRUE;
	uart.status = UWAIT;
	
	while(1) {
		if (kbhit() && uart.rxbuffer == 0x0A) {
			uart.rxbuffer = RXEMPTY;
			puts("Welcome to 16C84");
			crlf(); puts("C84>");
		}

		if (!tasks[LED1])
			task_led1(20);
		
		if (!tasks[LED2])
			task_led2(0xff-20);
	}
}


 
Nästa steg blir att avkoda Modbus meddelanden.

.
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
Skriv svar