Está en la página 1de 28

PicManabyRedRaven

Inicio.Mapa.Presentacin.ElectrnicaBsica.Experimentos.Proyectos.CCSC.C30.Invitados.Eagle.Conceptos
Datasheets.IC's.USB.TrucoseIdeas.CajndeSastre.Recursos.Enlaces.RedPic.Noticias.Histrico.Visitas

Buscar
Bsquedapersonalizada

ElRincndelCCSC1Parte

InstalarAres
Gratis

EllenguajeCeselqueusopordefecto
parael90%demisprogramas.Aquos
muestroalgunosejemplosdecmo
hacercosasconesteidioma.Todos
ejemplosquesemuestranenesta
seccinsehanrealizadousandoelPCW
PICCdeCCS(Veriones3.242a4.096
segndepende)

DescargaGratisPrueba
deVelocidadRpido
con
InternetSpeedTracker!

MsCCSC:1234

ndiceGeneral:

TemplateparaelusodelaInterrupcinRTCCmedianteelTIMER0
Laprimerayquizslamasutilizadadelasinterrupciones,porejemploes
labsicaparalosRelojesenTiempo(casi)Real.

TemplateparaelusodelaInterrupcinRDAdelaUSART
UtilsimapararecibirdatosdesdeelPCmientrasnuestromicrosededica
aotracosamariposa.

UnaaplicacinprcticadeRTCC:Cronopic1.0
ContandosegundosyminutosconnuestroPICymostrndolossobre4
displaysde7segmentosmultiplexados.

BIN2BCD
paraenviarnuestrosbytesalosDisplaysde7segmentos.

FlexLCD
unacompletalibreraparamanejarunmduloLCDconlaposibilidadde
configurarlospinesausar.

Modificandoelanchodeunpulso,generadoconRTCC,mediante

ordenesRS232.OunPWMporSoftware.

UnalibrerapararastrearunTecladomatricial4x4
Listaparausar(yconfigurable).

ProcesadordecomandosvaRS232(conBufferderecepcin)
ParadarrdenesconmasenjundiaanuestroPIC

ControlandounSERVOconelPICdesdenuestroPC
OtodoloquesiemprequisosabersobrelosServomotoresynuncase
atreviapreguntar

StringsDemoocomosepuedenmanejarlascadenasennuestroPIC
Notevoyaexplicarquesnlospunterosolosarraysperopuedesverlos
funcionar.

RROSv2.0LaEEPROMinternapuestaanuestroservicio
EscribiendoorecuperandodatosdelaEEPROMinternadesdenuestroPC
vaRS232.

FuncionesdeDateyTimeparaPIC
ColeccindefuncionesparamanejarAos,meses,semanas,das,horas,
minutosysegundos.

LeeryEscribirenlaEEPROMinternadelPICvariablesint16bits(2
bytes)
Paracuandonuestravariableesmayorqueelbyte

Lib_Int_EEPROMFuncionesespecialesparaLeeryEscribirlaEEPROM
internadelPIC
ParacuandoqueremosutilizarotrasvariablesdistintasalInt8.

RutinadeconversindeNmerosArbigosaNmerosromanos
ParaquenuestroPIChableenLatnClsico.

ManejandounArraydebitsIyManejandounArraydebitsII
(simuladoenCCSCquenoloimplementa)
ParaquenuestroPICnodesperdiciememoria.

TecladoMatricial4x4conDriverAnalgico
Unatcnicaparaahorrarpinesdelpic.

Controlando8Servosconunasolainterrupcin.
Unatcnicaparaconseguirestabilidadypotencia.

TeorayPraxisdelaComunicacionesTTL
HablandoconelPIChastaporloscodos.

SerieTcnicasenC:

TcnicasenC:ndice
Unpuntodeentradaaestanuevaseriedeartculos.

TcnicasenC:Midiendounpulso.1Parte
MidiendoentiempoqueunpulsopermaneceenaltomedianteINTEXT.

TcnicasenC:Midiendounpulso.2Parte
MidiendoentiempoqueunpulsopermaneceenaltomedianteINTCCPen
modoCapture.

TcnicasenC:Midiendounpulso.3Parte
MidiendoentiempoqueunpulsopermaneceenaltomedianteINTRB.

TcnicasenC:Midiendounpulso.4Parte
Midiendoelpulsocompleto.PeriodoyFrecuencia.

TcnicasenC:Generandounpulso.1Parte
Generandounaondacuadradasimtricade2KhzmedianteINTRTCC.

TcnicasenC:Generandounpulso.2Parte
Generandounaondacuadradasimtricade2KhzmedianteINTCCPen
modoCompare.

TcnicasenC:LibreradeFunciones"tiles"
UnartculomuytilsobrefuncionestilesysuimplementacinenCCSC.

Nota1:
LosMicrosusadossonel16F628,el16F876Ayel18F4550peropuedeser
fcilmenteadaptadoaotrosmodelosdePIC.Ocasionalmenteseusan
tambinlos18F1320y18F2550.
Todoslostiemposestncalculadosparacristalesde4Mhzy20Mhz,
salvoenlos18F4550y18F2550enfuncionesdeUSBque"corren"a48
MhzmedianteelPLLinterno.

TemplateparaelusodelaInterrupcinRTCCmedianteelTIMER0

LainterrupcinRTCCseproducecadavezqueelcontadorTIMER0pasade
FFha00h.
ElTIMER0haceuncmputocompletode00haFFhcada512S,sin
embargoestetiempopuedesercambiadomedianteunpreescaleroseaun
divisor,ajustable.Lostiemposgeneradosparacadaconfiguracinson(Ver
Nota1):

:2
:4
:8
:16
:32
:64
:128
:256

->
->
->
->
->
->
->
->

512
1.0
2.0
4.0
8.1
16.3
33.3
66.6

S al mnimo preescaler posible.


mS
mS
mS
mS
mS
mS
mS al mximo preescaler posible.

ElTemplatequepropongousaunPreescalerde128paraproduciruna
interrupcinRTCCcada33.3mSyascada30vecesqueseproducecambiode
estadolavariableFlag,osea33.3x30=999mS.

ExactamenteesteTemplateeselutilizadoenelexperimentoWinkIntcenel
quehacemosparpadearunLedcada0.25segundos(aproximadamente).

TemplateparaelusodelaInterrupcinRTCCmedianteelTIMER0

#include <16f628.h> // Selecciona el PIC


#fuses XT,NOWDT,NOPROTECT,PUT,BROWNOUT // Opciones de
configuracin
#use delay(clock=4000000) // Velocidad del
Cristal : 4 Mhz
byte const NInts=30; // Numero de
interrupciones para 1 Segundo
// VARIABLES GLOBALES
char C_Ints=0; // Contador de
Interrupciones ocurridas
char Flag=0; // Flag que cambia cada
NInts interrupciones

#int_RTCC // Interrupcin por


desbordamiento
RTCC_isr() { // del TIMER0 RTCC
if(C_Ints > NInts){ // Si las ints
ocurridas > ints para 1 Seg.
if(Flag==0){

Flag=1;
}
else{
Flag=0;
}
C_Ints=0; // Reinicializo
Contador de Ints
}
++C_Ints; // Incremento el nmero
de interrupciones
} // Ocurridas

void main(void) {
setup_counters(RTCC_INTERNAL,RTCC_DIV_128);//
Interno, Presescaler 128
setup_timer_1(T1_DISABLED);//
cada 33.3 milisegundos
setup_timer_2(T2_DISABLED,0,1);//
30 RTCC
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
enable_interrupts(INT_RTCC);//
Interrupcin RTCC
enable_interrupts(global);//
Interrupciones

TIMER0: Clock
para una RTCC
-> 1 Segundo =

Habilito
Habilito

do{ // Bucle infinito


if(Flag==K){}
else
{// si ha cambiado
Flag ...
// AQUI HAGO LO QUE DESEE CADA 1 SEGUNDO
k=Flag;// Guardo estado
anterior de Flag
}
}While(TRUE);
}

DescargarTemplateRTCC

HaciendoClicksobrelaimageninferiorpuedeverseunmomentodela
simulacinrealizadaconelprogramaanteriorhaciendoparpadearunLed
conectadoaPORTB.0.(LasimulacinestrealizadaconelPICSimulatorIDE
5.22deOshonSoft)

TemplateparaelusodelaInterrupcinRDAdelaUSART

LainterrupcinRDAseproducecadavezqueenlaUSARThaydisponibleun
carcterparaserledo.

ElbufferderecepcindelaUSARTdelPIC16F628disponedesolo2bytes
porloqueesimportantsimoeldescargarlotalcomosevanrecibiendolos
caracteres,deestaformaevitamoselqueseveantristementeperdidosenel
limboserie.

EsteTemplatedemuestracmorecibircadacarcterquellegahacindole
ecodesdeelprogramaprincipal.Sinecesitamosrecogermuchoscaracteresy
nuestrarutinaprincipaleslargayfarragosaesinteresanterecibirmediante
RDAloscaractereseirlosalmacenandoenunBUFFERmsamplioparaser
posteriormentetratados.

TemplateparaelusodelaInterrupcinRDAdelaUSART
#include <16f628.h> // Selecciona el PIC
#fuses XT,NOWDT,NOPROTECT,NOLVP,PUT,BROWNOUT // Opciones de
configuracin
#use delay(clock=4000000) // Velocidad del Cristal : 4 Mhz
#use standard_io(b)
#use rs232(baud=9600, xmit=PIN_B2, rcv=PIN_B1) // Definicin
del RS232
char Keypress=' ';
#int_rda
void serial_isr() {
Keypress=0x00;
if(kbhit()){

Keypress=getc();
if(Keypress!=0x00){
putchar(keypress);
keypress=0x00;
}
}
}

void main() {
enable_interrupts(global);
enable_interrupts(int_rda);
printf("\r\n\Listen on RS232 (Int)\r\n");
do {

} while (TRUE);
}

DescargarTemplateRDA

UnaaplicacinprcticadeRTCC:Cronopic1.0

Esteartculonospresentaunmtodorazonableparaimplementarun
cronmetroennuestroPIC.HacemosusoenldelTemplateparaelusodela
InterrupcinRTCCmedianteelTIMER0descritomsarribaascomodel
HardwaredescritoenHardwaredeExperimentos:4x7Segmentos.

Paraesteejemplovamosacambiardemicroynosmudamosdel16F628al
16F876A,aunquenuestroprogramafuncionaraexactamenteigualenunoque
enotroconsolocambiarelincludecorrespondiente.

NoestarademsquelediesesunvistazoalartculoLosCristalesyEl
Tiempodondediscutimoslosclculosquedespusvamosautilizarennuestro
Cronopic1.0.

Heintentadocomentarsuficientementeelcdigofuente,sinembargodebo
explicaralmenosquetcnicaheseguidoparadesarrollarlo.Elasuntoescomo
sigue:

Cronopic1.0habilitalainterrupcinRTCCusandounCristalde4Mhzycon
unPreescalerde1:256porloqueseproduceundesbordamientocada66.6
ms.Con15interrupcionesdestastenemos15*66.6=999ms,o
aproximadamenteunsegundo.

Asqueloquevamosaimplementaresuncontadordesegundosquesolose
incrementacada15RTCC'sconsecutivas.Paraestoutilizamoslavariable
nRTCCquecuandoesigualalaconstanteRTCCxSpermiteincrementarla
variablesegundo,queesnuestrocontadordesegundostranscurridos.Si
segundopasade59incrementamosminuto,ysistesobrepasaelvalorde

59volvemosacomenzarreinicindoloa0.Estodentrodelarutinade
tratamientodelainterrupcinRTCC.

Enelbucleprincipal,yeterno,dentrodeMain()habilitamosunavariable
ksegundoquesinoesigualasegundonosindicaqueelsegundoactualha
cambiado.Alocurrirestodisparamoslaactualizacindelosvaloresasacarpor
nuestros7segmentos.Paraellollamamosatime2bcd()queeslarutinaque
vaaformatearsegundoyminutoparaquepuedanvervisualizados.
Inmediatamentehacemosksegundoigualasegundoparaquenovolvamosa
hacerestomismohastaquenocambieelsegundoactual,quevolveremosa
detectarcomparndoloconksegundo.

Elformateorealizadoentime2bcd()consisteenconvertirsegundoy
minutodesusactualesvaloresbinariosaBCDqueeselqueaceptaeldriver
delosdisplays.EstaconversincargaconsusnuevosvaloreslasvariablesD1
yD2quesonlosdgitosLowyHightenqueseconviertesegundoyD3yD4
quesonlosdeminuto.

Dentrodelbucleprincipaldemain()sellamaconstantementealarutina
display_reloj()queeslaencargadadeponerlosvaloresdeD1,D2,D3yD4
eneldriverdelosdisplays.

Yesoesto,ocasitodoyaqueesteCronopictieneunerrorde1milisegundo
porcadasegundocontadoporloquenodebestenerunafeabsolutaenlsitu
vidadependedeello.Nohequeridocomplicarloenestaprimeraversinpero
noesdifcilcompensarestedesfaseusandoelmtodoquehebautizadocomo
picbisisestoyquelorealizaremosparaversionesposterioresdeCronopic.

Cronopic1.0

#include <16f876a.h> // Selecciona el PIC


#fuses XT,NOWDT,NOPROTECT,PUT,BROWNOUT // Opciones de configuracin
#use delay(clock=4000000) // Velocidad del Cristal : 4 Mhz
#use standard_io(B) // PORTB en estandar IO digital
#use
fixed_io(b_outputs=PIN_B0,PIN_B1,PIN_B2,PIN_B3,PIN_B4,PIN_B5,PIN_B6,PIN_B7)
char const RTCCxS=15; // Nmero de RTCC's para 1 segundo con 4 Mhz / 1:256.
// VARIABLES GLOBALES
int
int
int
int
int
int
int
int
int

nRTCC=0x00;
segundo=0x0;
minuto=0x0;
D1=0x00;
D2=0x00;
D3=0x00;
D4=0x00;
l_digit, h_digit;
i;

//
//
//
//

Contador de interrupciones RTCC completas


Segundos del Reloj
Minutos del Reloj
Contenido de los Displays

// Resultado de la conversin bin2bcd


// index general

void testdisplays(void); // Funcin que testea los displays


void display_reloj(void); // Funcin que muestra el contenido del reloj
void time2bcd(void); // Funcin que convierte minutos y segundos a 4 x
BCD

void bin2bcd(int valor); // Funcin que convierte de Binario a BCD


#int_RTCC // Interrupcin por desbordamiento
RTCC_isr() { // del TIMER0 RTCC
if(++nRTCC==RTCCxS){
nRTCC=0x00;
if(++segundo>59){
segundo=0;
if(++minuto>59){
minuto=0;
}
}
}
}
void main(void) {
int ksegundo=0x00;
setup_counters(RTCC_INTERNAL,RTCC_DIV_256); // TIMER0: Clock Interno y
Preescaler
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
enable_interrupts(INT_RTCC);// Habilito Interrupcin RTCC
enable_interrupts(global);// Habilito Interrupciones

do{ // Bucle infinito


if(segundo!=ksegundo){ // si cambia el segundo actualizo las
time2bcd(); // variables con lo que hay que mostrar
ksegundo=segundo;
}
display_reloj(); // Muestra constantemente
}While(TRUE);
}
void display_reloj(void){ // Funcin que muestra el contenido del reloj

output_b(D1); // Muestro 1er carcter de segundo


output_high(PIN_B4);
delay_us(30);
output_b(D2); // Muestro 2do carcter de segundo
output_high(PIN_B5);
delay_us(30);

output_b(D3); // Muestro 1er carcter de minuto


output_high(PIN_B6);
delay_us(30);
output_b(D4); // Muestro 2do carcter de minuto
output_high(PIN_B7);
delay_us(30);

}
void time2bcd(void){ // Funcin convierte minutos y segundos a 4 x BCD

bin2bcd(segundo);
D1 = l_digit;
D2 = h_digit;
bin2bcd(minuto);
D3 = l_digit;
D4 = h_digit;

// Paso de binario a BCD el segundo y actualizo


// contenido a mostrar
// Paso de binario a BCD el minuto y actualizo
// contenido a mostrar

}
void bin2bcd(int valor){ // Funcin que convierte de Binario a BCD
h_digit=0;
if (valor>=10){
do{
valor-=10;
h_digit++;
} while (valor>=10);
}
l_digit=valor;
}

Bin2BCD

CuandoqueremosutilizarunodeesosdriversparaDisplaysde7segmentos
quesoloaceptandatosenBCDseimponeunarutinaquenosconviertanuestro
byteentanestrambticoBinaryCodeDecimal.

Ahosdejounafuncinpararealizarlanecesariaconversin:

Bin2BCD(1):

int l_digit, h_digit; // resultado de la conversion


bin2bcd

void bin2bcd(int valor){ // Funcion que convierte de


Binario a BCD
h_digit=0;

if (valor>=10){
do{
valor-=10;
h_digit++;
}while (valor>=10);
}
l_digit=valor;
}

UnalibreraparamanejarunLCDconlosPinesquedeseemos:flex_lcd.c

AquiosbrindounalibreraparamanejarunLCDcon4bitsdedatos,
pudiendoestablecerlospinesquedeseemosparaellosyparalosdecontrolE,
R/WyRS.Slohayquemodificarlos#definesdelosmismos.

Parausarlasolodebisincluirelcorrepondiente#include"flex_lcd.c"en
vuestroprograma.

flex_lcd.c
// flex_lcd.c
// Change these pins to fit your own board.
#define
#define
#define
#define

LCD_DB4
LCD_DB5
LCD_DB6
LCD_DB7

PIN_B4
PIN_B5
PIN_B6
PIN_B7

#define LCD_RS PIN_C0


#define LCD_RW PIN_C1
#define LCD_E PIN_C2
// If you only want a 6-pin interface to your LCD, then
// connect the R/W pin on the LCD to ground, and comment
// out the following line.
#define USE_LCD_RW 1
//========================================
#define lcd_type 2 // 0=5x7, 1=5x10, 2=2 lines

#define lcd_line_two 0x40 // LCD RAM address for the 2nd line

int8 const LCD_INIT_STRING[4] =


{
0x20 | (lcd_type << 2), // Func set: 4-bit, 2 lines, 5x8
dots
0xc, // Display on
1, // Clear display
6 // Increment cursor
};

//------------------------------------void lcd_send_nibble(int8 nibble)


{
// Note: !! converts an integer expression
// to a boolean (1 or 0).
output_bit(LCD_DB4, !!(nibble & 1));
output_bit(LCD_DB5, !!(nibble & 2));
output_bit(LCD_DB6, !!(nibble & 4));
output_bit(LCD_DB7, !!(nibble & 8));

delay_cycles(1);
output_high(LCD_E);
delay_us(2);
output_low(LCD_E);

//----------------------------------// This sub-routine is only called by lcd_read_byte().


// It's not a stand-alone routine. For example, the
// R/W signal is set high by lcd_read_byte() before
// this routine is called.
#ifdef USE_LCD_RW
int8 lcd_read_nibble(void)
{
int8 retval;
// Create bit variables so that we can easily set
// individual bits in the retval variable.
#bit retval_0 = retval.0
#bit retval_1 = retval.1
#bit retval_2 = retval.2
#bit retval_3 = retval.3
retval = 0;
output_high(LCD_E);
delay_cycles(1);
retval_0 = input(LCD_DB4);
retval_1 = input(LCD_DB5);

retval_2 = input(LCD_DB6);
retval_3 = input(LCD_DB7);
output_low(LCD_E);
return(retval);
}
#endif
//--------------------------------------// Read a byte from the LCD and return it.
#ifdef USE_LCD_RW
int8 lcd_read_byte(void)
{
int8 low;
int8 high;
output_high(LCD_RW);
delay_cycles(1);
high = lcd_read_nibble();
low = lcd_read_nibble();
return( (high<<4) | low);
}
#endif
//---------------------------------------// Send a byte to the LCD.
void lcd_send_byte(int8 address, int8 n)
{
output_low(LCD_RS);
#ifdef USE_LCD_RW
while(bit_test(lcd_read_byte(),7)) ;
#else
delay_us(60);
#endif

if(address)
output_high(LCD_RS);
else
output_low(LCD_RS);

delay_cycles(1);
#ifdef USE_LCD_RW
output_low(LCD_RW);
delay_cycles(1);
#endif

output_low(LCD_E);
lcd_send_nibble(n >> 4);
lcd_send_nibble(n & 0xf);
}
//---------------------------void lcd_init(void)
{
int8 i;
output_low(LCD_RS);
#ifdef USE_LCD_RW
output_low(LCD_RW);
#endif
output_low(LCD_E);
delay_ms(15);
for(i=0 ;i < 3; i++)
{
lcd_send_nibble(0x03);
delay_ms(5);
}
lcd_send_nibble(0x02);
for(i=0; i < sizeof(LCD_INIT_STRING); i++)
{
lcd_send_byte(0, LCD_INIT_STRING[i]);
// If the R/W signal is not used, then
// the busy bit can't be polled. One of
// the init commands takes longer than
// the hard-coded delay of 60 us, so in
// that case, lets just do a 5 ms delay
// after all four of them.
#ifndef USE_LCD_RW
delay_ms(5);
#endif
}
}
//---------------------------void lcd_gotoxy(int8 x, int8 y)
{
int8 address;
if(y != 1)

address = lcd_line_two;
else
address=0;
address += x-1;
lcd_send_byte(0, 0x80 | address);
}
//----------------------------void lcd_putc(char c)
{
switch(c)
{
case '\f':
lcd_send_byte(0,1);
delay_ms(2);
break;
case '\n':
lcd_gotoxy(1,2);
break;
case '\b':
lcd_send_byte(0,0x10);
break;
default:
lcd_send_byte(1,c);
break;
}
}
//-----------------------------#ifdef USE_LCD_RW
char lcd_getc(int8 x, int8 y)
{
char value;
lcd_gotoxy(x,y);
// Wait until busy flag is low.
while(bit_test(lcd_read_byte(),7));
output_high(LCD_RS);
value = lcd_read_byte();
output_low(lcd_RS);
return(value);
}
#endif
void lcd_setcursor_vb(short visible, short blink) {
lcd_send_byte(0, 0xC|(visible<<1)|blink);

Descargarflex_lcd.c

Modificandoelanchodeunpulso,generadoconRTCC,medianteordenes
RS232:

Esteejemplonosmuestracmopodemosrealizarelultrafamosoled
parpadeando,perorealizadoconlainterrupcinRTCCdelTimer0,yrecibiendo
ordenesvaRS232parapodermodificarelanchodelpulso,olaseparacin
entredospulsossucesivos.

Conceptos,ideasytcnicasutilizadas:
CadavezquesaltalainterrupcinRTCCcambiamosdeLOWaHIGH,de
HIGHaLOW,elpinRB0.ParaelloutilizamoslavariableLedquenosindicacual
fueelltimocambioparapoderhacerelcomplementario.
CadavezquerealizamosdichocambiodeLOWaHIGH,odeHIGHaLOW,
cargamoselcontadordelTimer0conunvalorvariablequepodemosajustar
externamente:OffsetLparaelsemiperiodoLOWyOffsetHparaelsemiperiodo
HIGH
(SiOffsetLyOffsetHsonigualacero,comoeselcasocuandoacabamosde
resetearelmicro,tenemosunaondacuyoperiodoesexactamenteiguala2*
RTCC:UnaRTCCcompletacondeponemosRB0enHIGHyotraRTCCcompleta
enlaqueponemosRB0enLOW)
RecibimosdistintasordenesdesdeelRS232conlascualesmodificamoslos
valoresdeOffsetHyOffsetL.
Cualquiervalormayorque0enOffsetHoenOffsetLhacequealproducirsela

correspondienteinterrupcinRTCC,quecomosabissaltaalpasarelTimer0de
FFha00h,secargeelTimer0condichovalor:Porloquelasiguiente
interrupcinsermascorta,ydeformadirectamenteproporcionalalvalor
cargado,yaqueenvezdetenerqueesperaraqueTimer0recorratodosu
contadorde00haFFhlovahahacersolamentedesdeOffsetH,uOffsetL,hasta
FFh.
*CuantomayorseaOffsetHmenostiempovaaestarRB0enHIGH.
*CuantomayorseaOffsetLmenostiempovaaestarRB0enLOW
SiOffsetHyOffsetLtienenelmismovalorlaondaproducidatendriguales
ambossemiperiodos,convaloresdistintosserporendedistintosambosypor
ellonosvariarlafrecuencia.Paramantenerlafrecuenciaconstante,oel
periodoconstante,debemosampliarodisminuircomplementariamenteambos
Offset.Loqueseincrementeunodeellosdebemosdisminuirelotro,o
viceversa.
HemosincluidounavariableOndaconlaquepodemosordenarleaquparte
denuestropulsovaaafectarlasiguienteorden:"C"(decuadradaparaambos
semiperiodos)"H"paraelsemiperiodoAltoy"L"paraelsemiperiodoBajo.
EsteejemplitoesbsicamenteunPWMrealizadoporSoftwarequepuedeser
fcilmenteadaptadoacualquiermicroPIC,porejemploparamanejarunServo.

Fuentepwm_rtcc_232.c

#include <16f876a.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP,PUT,BROWNOUT
#use delay(clock=4000000)
#use standard_io(b)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)

int Led=0x00;
int Offseth=0x00;
int Offsetl=0x00;
char Onda='C';
char Keypress=' ';
void eco_offset(void);
#int_rda
void rda_isr() {
Keypress=0x00;
if(kbhit()){
Keypress=getc();
}
}
#int_RTCC
RTCC_isr(){
// RB0
Switch(Led){

Case 0: output_high(PIN_B0);
set_timer0(Offseth);
break;
Case 1: output_low(PIN_B0);
set_timer0(Offsetl);
break;
}
if(++Led>1){
Led=0;
}
}
void main() {
setup_counters(RTCC_INTERNAL,RTCC_DIV_2); // TEST
enable_interrupts(int_rda);
enable_interrupts(global);

printf("\r\n\PWM (RTCC) OS\r\n");

Onda='C';
Offseth=0x00;
Offsetl=0x00;
enable_interrupts(INT_RTCC);

do {
if(Keypress!=0x00){
switch(Keypress){
// Tipo de Onda
case 'c': Onda='C';
break;
case 'h': Onda='H';
break;
case 'l': Onda='L';
break;
// Incrementando y decrementando periodos
case '+': if(Onda=='C'){ ++Offseth; ++Offsetl; }
if(Onda=='H'){ ++Offseth; }
if(Onda=='L'){ ++Offsetl; }
break;
case '-': if(Onda=='C'){ --Offseth; --Offsetl; }
if(Onda=='H'){ --Offseth; }
if(Onda=='L'){ --Offsetl; }
break;
// Periodos Prefijados
case '1': if(Onda=='C'){ Offseth=0; Offsetl=0; }
if(Onda=='H'){ Offseth=0; }

if(Onda=='L'){
break;
case '2': if(Onda=='C'){
if(Onda=='H'){
if(Onda=='L'){
break;
case '4': if(Onda=='C'){
if(Onda=='H'){
if(Onda=='L'){
break;
}
eco_offset();
Keypress=0x00;
}
} while (TRUE);

Offsetl=0; }
Offseth=128; Offsetl=128; }
Offseth=128; }
Offsetl=128; }
Offseth=192; Offsetl=192; }
Offseth=192; }
Offsetl=192; }

}
void eco_offset(void){
printf("\r\nOnda %c h%u l%u\r\n",Onda,Offseth,Offsetl);
}

Descargarpwm_rtcc_232.c

UnalibrerapararastrearunTecladomatricial4x4

Aqutenisunalibreraquepermiteleeruntecladomatricialde16teclas(4
filasx4columnas).Solotenisqueincluircon#includeestalibreraen
vuestroprogramaprincipalyllamaralafuncinkbd_getc()dondelo
necesitis.
Nota:Estalibreraestaderivadadelaoriginalincluidaen\driversdelCCSPIC
C.Encursivamarcoloscambiosqueherealizadoparaadaptarlaami
hardwareparticular.

kbd_lib.c

///////////////////////////////////////////////////////////////////////////
//// kbd_lib.c by Redraven ////
//// ////
//// Derived from kbdd.c ////
//// Generic keypad scan driver ////
//// ////
//// kbd_init() Must be called before any other function. ////
//// ////
//// c = kbd_getc(c) Will return a key value if pressed or /0 if not ////
//// This function should be called frequently so as ////

//// not to miss a key press. ////


//// ////
///////////////////////////////////////////////////////////////////////////
//// (C) Copyright 1996,1997 Custom Computer Services ////
//// This source code may only be used by licensed users of the CCS C ////
//// compiler. This source code may only be distributed to other ////
//// licensed users of the CCS C compiler. No other use, reproduction ////
//// or distribution is permitted without written permission. ////
//// Derivative programs created using this software in object code ////
//// form are not restricted in any way. ////
////////////////////////////////////////////////////////////////////////////
////////////////// The following defines the keypad layout on port D
// Un-comment the following define to use port B
#define use_portb_kbd TRUE
// Make sure the port used has pull-up resistors (or the LCD) on
// the column pins

#if defined(__PCH__)
#if defined use_portb_kbd
#byte kbd = 0xF81 // This puts the entire
#else
#byte kbd = 0xF83 // This puts the entire
#endif
#else
#if defined use_portb_kbd
#byte kbd = 6 // on to port B (at address
#else
#byte kbd = 8 // on to port D (at address
#endif
#endif

structure
structure

6)
8)

#if defined use_portb_kbd


#define set_tris_kbd(x) set_tris_b(x)
#else
#define set_tris_kbd(x) set_tris_d(x)
#endif
//Keypad connection: (for example column 0 is B0)
#define
#define
#define
#define

COL0
COL1
COL2
COL3

(1
(1
(1
(1

<<
<<
<<
<<

0)
1)
2)
3)

//
//
//
//

PIN_B0
PIN_B1
PIN_B2
PIN_B3

#define
#define
#define
#define

ROW0
ROW1
ROW2
ROW3

(1
(1
(1
(1

<<
<<
<<
<<

4)
5)
6)
7)

//
//
//
//

PIN_B4
PIN_B5
PIN_B6
PIN_B7

#define ALL_ROWS (ROW0|ROW1|ROW2|ROW3)


#define ALL_PINS (ALL_ROWS|COL0|COL1|COL2|COL3)

// Keypad layout:
char const KEYS[4][4] = {{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}};
#define KBD_DEBOUNCE_FACTOR 33 // Set this number to apx n/333 where
// n is the number of times you expect
// to call kbd_getc each second
void kbd_init() {
}

char kbd_getc( ) {
static byte kbd_call_count;
static short int kbd_down;
static char last_key;
static byte col;

byte kchar;
byte row;
kchar='\0';
if(++kbd_call_count>KBD_DEBOUNCE_FACTOR) {
switch (col) {
case 0 : set_tris_kbd(ALL_PINS&~COL0);
kbd=~COL0&ALL_PINS;
break;
case 1 : set_tris_kbd(ALL_PINS&~COL1);
kbd=~COL1&ALL_PINS;
break;
case 2 : set_tris_kbd(ALL_PINS&~COL2);
kbd=~COL2&ALL_PINS;
break;
case 3 : set_tris_kbd(ALL_PINS&~COL3);
kbd=~COL3&ALL_PINS;
break;
}
if(kbd_down) {
if((kbd & (ALL_ROWS))==(ALL_ROWS)) {
kbd_down=false;
kchar=last_key;
last_key='\0';
}
} else {
if((kbd & (ALL_ROWS))!=(ALL_ROWS)) {
if((kbd & ROW0)==0)
row=0;
else if((kbd & ROW1)==0)

row=1;
else if((kbd & ROW2)==0)
row=2;
else if((kbd & ROW3)==0)
row=3;
last_key =KEYS[row][col];
kbd_down = true;
} else {
++col;
if(col==4)
col=0;
}
}
kbd_call_count=0;
}
set_tris_kbd(ALL_PINS);
return(kchar);
}

Descargarkbd_lib.c

ProcesadordecomandosvaRS232(conBufferderecepcin)

Hasta ahora, en nuestros trabajos anteriores, utilizbamos comandos


enviados va RS232 consistentes en un nico carcter, con el que
hacamos ejecutar alguna de las funciones que nuestro programa
implementaba. Este mtodo es de muy corto alcance por dos motivos
fundamentales: Primero porque eran ejecutados inmediatamente tan
prontoeranrecibidosysegundoporquenopodamosenviarledatos(una
cadenadecaracteres)paraserprocesados.
En este nuevo artculo vamos a solucionar exactamente eso. He
imaginado un programa que admite dos comandos de alto nivel: uno de
lectura"\r"sinargumentosyotrodeescritura"\w"quevaseguidodeun
argumentotanlargocomonecesitemos.
Paramanejarelenvodeamboscomandosascomoel/losargumentos
necesariosheimplementadolobsicoparamanejarelbufferenelPIC,a
base de teclas nicas, cada una con su funcin: [INTRO] 0x0D para
indicar que hemos terminado de escribir el comando, [RETROCESO]
0x08 para borrar el ltimo carcter enviado y [ESCAPE] 0x1B para
borrar todo el contenido actual del buffer. (Como podis imaginar este
miniprograma puede complicarse hasta el infinito y solo tenis que
aadircomandosavuestraenteradiscrecin).
El programa va entonces recibiendo caracteres, uno tras otro, y
guardndolosenelBuffer.Sirecibeelcomando[INTRO]habilitaun flag
para que se procese el comando, y tras ser procesado borra el buffer y
vuelve a empezar. Las otras dos teclas de [RETROCESO] y [ESCAPE]
lasusamosparaeditarelcontenidodelbufferantesdeenviarle la orden
deprocesado.

Heintentadocomentarprofusamenteelprogramaparaquesea
meridianamenteclarosufuncionamientoyhacerasinnecesariasmas
explicaciones:

command_232_buffered.c

#include <16f876a.h> // Definiciones del PIC 16F876A


#fuses XT,NOWDT,NOPROTECT,NOLVP,PUT,BROWNOUT // Los Fuses de
siempre
#use delay(clock=4000000) // Oscilador a 4 Mhz
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)// RS232 Estndar
// CONSTANTES
/////////////////////////////////////////////////////////////////
int const lenbuff=32; // Longitud de buffer, Ajustar
// a lo que desees (o te sea posible)
// VARIABLES EN RAM
///////////////////////////////////////////////////////////
int xbuff=0x00;
char cbuff[lenbuff];
char rcvchar=0x00;
int1 flagcommand=0;

//
//
//
//

ndice: siguiente char en cbuff


Buffer
ltimo carcter recibido
Flag para indicar comando disponible

// Declaracin de Funciones
///////////////////////////////////////////////////
void inicbuff(void);
int addcbuff(char c);
void echos(char c);
void procesa_comando(void);

//
//
//
//

Borra buffer
aade carcter recibido al buffer
Eco selectivo sobre RS232
Procesa comando

// INTERRUPCIONES
/////////////////////////////////////////////////////////////
#int_rda
void serial_isr() { // Interrupcin recepcin serie USART
rcvchar=0x00;
if(kbhit()){
rcvchar=getc();
addcbuff(rcvchar);
echos(rcvchar);
}
}

//
//
//
//
//

Inicializo carcter recibido


Si hay algo pendiente de recibir ...
lo descargo y ...
lo aado al buffer y ...
hago eco (si procede).

// Desarrollo de Funciones
////////////////////////////////////////////////////

void echos(char c){ // Echo selectivo --------------------- switch(c){


case 0x0D:
[Intro]

case 0x08:
[Retroceso]

case 0x1B:
[Escape]

default:
carcter
}
}

printf(" [Ent] "); // Si he pulsado la tecla


break;
printf(" [Del] "); // Si he pulsado la tecla
break;
printf(" [Esc] "); // Si he pulsado la tecla
break;
putc(rcvchar); // Echo de cualquier otro

void inicbuff(void){ // Inicia a \0 cbuff ------------------ int i;


for(i=0;i<lenbuff;i++){
cbuff[i]=0x00;
}
xbuff=0x00;

// Bucle que pone a 0 todos los


// caracteres en el buffer
// Inicializo el ndice de siguiente
// carcter

int addcbuff(char c){ // Aade a cbuff -----------------------

switch(c){
case 0x0D: // Enter -> Habilita Flag para procesar
flagcommand=1; // Comando en Main
break;
case 0x08: // Del -> Borra ltimo carcter del
Buffer
if(xbuff>0) cbuff[--xbuff]=0x00;

break;
case 0x01B: // Esc -> Borra el Buffer completamente
inicbuff();
break;
default:
cbuff[xbuff++]=c; // Aade carcter recibido al Buffer
}
}

// Programa Principal
/////////////////////////////////////////////////////////
void main() {
inicbuff(); // Borra buffer al inicio

printf("\r\n\** RS232 Buffered **\r\n\r\n"); // Presenta men


printf("[Enter] Procesa comando\r\n");
printf("[Escape] Borra todo el buffer\r\n");
printf("[Delete] Borra ltimo carcter del buffer\r\n");
printf("[\\w] Comando Escribe\r\n");
printf("[\\r] Comando Lee\r\n");
printf("\r\n");

enable_interrupts(int_rda); // Habilita Interrupcin RDA


enable_interrupts(global); // Habilita interrupciones
do {
if(flagcommand) procesa_comando(); // Si hay comando
pendiente
// de procesar ... lo
procesa.
} while (TRUE);
}
// Procesador de Comandos
/////////////////////////////////////////////////////
void procesa_comando(void){
int i;
char arg[lenbuff]; // Argumento de comando (si lo tiene)
flagcommand=0; // Desactivo flag de comando pendiente.
printf("\r\nProcesando ... "); // Monitorizo procesando ...
for(i=0;i<lenbuff;i++){ // Bucle que pone a 0 todos los
arg[i]=0x00; // caracteres en el argumento
}
if(cbuff[0]=='\\'&&cbuff[1]=='r'){ // Comparo inicio del buffer
con comando "\r"
printf("Leyendo ... "); // Aqui lo que deseemos hacer
con comando "\r"
}
if(cbuff[0]=='\\'&&cbuff[1]=='w'){ // Comparo inicio del buffer
con comando "\w"
i=2;
do{ // Extraemos argumento del buffer
arg[i-2]=cbuff[i]; // a partir del 3er byte y hasta \0.
}while(cbuff[++i]!=0x00);
printf("Escribiendo %s ... ",arg);// Aqui lo que deseemos

hacer con comando "\w"


// Monitorizamos el
argumento.
}
inicbuff(); // Borro buffer.
printf("Procesado.\r\n\r\n"); // Monitorizo procesado.
}

Descargarrs232_buffered.c

YporltimosolomequedamostrarlosresultadossobremimonitorRS232enelPC:

ProgramadeRecuperacin
CopiasdeSeguridadAutomticamentedesdetuPC.InstalaGratisAhora!

Nota:EstapginaWebestarepletadeimgenes,textos,logotiposydemsmaterialextradosde
losmasvariadosmediosdelosquenosoyniautornidepositariodeloscorrespondientesderechos
deautor,usoy/oreproduccin.SiUd.esdepositariodedichosderechosydeseaqueelmaterial
correspondienteseaeliminadodeestaWebnodudeenponerseencontactoconmigomediantee
mailyserinmediatamenteretirado.Gracias.

Visitas
Totales:221576Hoy:1Activas:1Vistas:221576
Estapginafuemodificadael0708201015:42:21

DmSoftWAMPEscribirUnreal

También podría gustarte