¿Vale la pena que queme neuronas tratando de aprender el C? ¿O bien desarrollo mi base de basic y esto me valdrá para toda la gama?
//-----------------------------------------------------------------------
// Dibuja una linea desde (x1,y1) a (x2,y2) de color (0 o 1)
//-----------------------------------------------------------------------
void OSD_linea(unsigned short x1, unsigned short y1, unsigned short x2, unsigned short y2, char color)
{
//Declaro variables-------------------
signed short x, y, incremento_x, incremento_y, distancia_x, distancia_y;
signed short P;
short i;
//Calculo las diferencias entre las coordenadas de origen y destino
distancia_x = fabs((signed short)(x2 - x1));
distancia_y = fabs((signed short)(y2 - y1));
//Inicializo x e y con las coordenadas de origen
x = x1;
y = y1;
//Calculo el sentido de los incrementos (positivos o negativos)
//en funcion de la posicion del origen y el destino
if(x1 > x2) incremento_x = -1; else incremento_x = 1;
if(y1 > y2) incremento_y = -1; else incremento_y = 1;
//Si la distancia horizontal es mayor a la vertical...
if(distancia_x >= distancia_y)
{ P = 2 * distancia_y - distancia_x;
for(i=0; i<=distancia_x; ++i)
{
OSD_punto(x, y, color);
if(P < 0)
{ P += 2 * distancia_y;
x += incremento_x; }
else
{ P += 2*distancia_y - 2*distancia_x;
x += incremento_x;
y += incremento_y;}
}
}
//Si la distancia vertical es mayor a la horizontal...
else
{ P = 2 * distancia_x - distancia_y;
for(i=0; i<=distancia_y; ++i)
{ OSD_punto(x, y, color);
if(P < 0)
{ P += 2 * distancia_x;
y += incremento_y; }
else
{ P += 2 * distancia_x - 2 * distancia_y;
x += incremento_x;
y += incremento_y; }
}
}
}
//-----------------------------------------------------------------------
Hola ElGarbe, quisiera agregar un pequeño tip sobre tu comentario. La función que publicas puede no ser tan portable como parece. Los tipos de variables y su peso cambia entre compiladores. Es importante seguir de cerca los tamaños de las variables.
Eso se soluciona muy rápidamente definiendo tipos comunes como el uint8_t o el uint64_t. Se declaran como typedefs o defines en cada arquitectura o compilador. El código deberá usar sólo esos tipos, nunca hay que usar int, long, short, etc. ya que sus tamaños dependen del compilador. Ya ves que hay int de 8 bits (CCS), int de 16 bits (XC8) o int de 32 bits (XC32). Pero si se usa un uint32_t y su typedef está correctamente ligado al tamaño real del compilador destino, entonces tu código sí que será portable al 100%.
Saludos. :)
+1 no hace mucho que aprendi lo que comentas y aun me cuesta acostumbrarme.
No estaría mal un post con "buenas practicas de programacion", no?
Saludos!
Uffff, cuantas cosas me faltan! Que lindo sería saber todo eso, estoy con unos desarrollos que serían mas que interesante aplicar todas esas pautas!+1 no hace mucho que aprendi lo que comentas y aun me cuesta acostumbrarme.
No estaría mal un post con "buenas practicas de programacion", no?
Saludos!
Hola ElGarbe, normalmente esas prácticas se pueden encapsular como estándares de programación. Cómo escribir nombres de variables, dónde usar typedefs, estilos de estructuración del código, estilos de funciones y dónde usarlas, sabiendo usar static, espacios en el código, etc.
Aquí un ejemplo...
http://users.ece.cmu.edu/~eno/coding/CCodingStandard.html
Facilitan mucho la vida... no sólo para hacer el código portable, sino también para hacerlo legible. ;-)
Uffff, cuantas cosas me faltan! Que lindo sería saber todo eso, estoy con unos desarrollos que serían mas que interesante aplicar todas esas pautas!
Tendrás algo como para ampliar en cuanto a layers?
Saludos!
Uffff, cuantas cosas me faltan! Que lindo sería saber todo eso, estoy con unos desarrollos que serían mas que interesante aplicar todas esas pautas!
Tendrás algo como para ampliar en cuanto a layers?
Saludos!
Mmmhh... ¿a qué te refieres con layers?
entiendo que en muchos sistemas complejos suele utilizarzo algo llamado HAL (hardware abstraction layer) y luego la capa del Sistema propiamente dicho, lo que facilita la portabilidad del sistema a otro hardware/uC...
Pero quizá esto de para otro post, no quiero desvirtuarle el post a Carlos.
Saludos y gracias!
#include "16F883.H" // Define el microcontrolador que se va a utilizar
#pragma origin = 0x10 // Dirección de origen del código
void main(void) { // Función principal (Siempre se llama main)
unsigned char i; // Declaro una variable llamada i como un byte (un caracter char) sin signo
TRISB.7 = 0; // Puerto B7 es una salida
i = 100; // La variable i es igual a 100
do {
PORTB.7 = 1; // El puerto B7 vale 1
PORTB.7 = 0;
} while (--i != 0); // Decrementa la variable i.
// Repite el bucle mientras i no valga cero
}
; CC5X Version 3.5, Copyright (c) B Knudsen Data
; C compiler for the PICmicro family
; ************ 2. Jan 2015 11:45 *************
processor 16F883
radix DEC
PORTB EQU 0x06
TRISB EQU 0x86
RP0 EQU 5
RP1 EQU 6
i EQU 0x20
GOTO main
; FILE mini.c
;#include "16F883.H" // Define el microcontrolador que se va a utilizar
;
;#pragma origin = 0x10 // Dirección de origen del código
ORG 0x0010
;
;void main(void) { // Función principal (Siempre se llama main)
main
; unsigned char i; // Declaro una variable llamada i como un byte (un caracter char) sin signo
;
; TRISB.7 = 0; // Puerto B7 es una salida
BSF 0x03,RP0
BCF 0x03,RP1
BCF TRISB,7
;
; i = 100; // La variable i es igual a 100
MOVLW 100
BCF 0x03,RP0
MOVWF i
; do {
; PORTB.7 = 1; // El puerto B7 vale 1
m001 BCF 0x03,RP0
BCF 0x03,RP1
BSF PORTB,7
; PORTB.7 = 0;
BCF PORTB,7
; } while (--i != 0); // Decrementa la variable i.
DECFSZ i,1
GOTO m001
; // Repite el bucle mientras i no valga cero
;}
SLEEP
GOTO main
END
; *** KEY INFO ***
; 0x0010 P0 14 word(s) 0 % : main
; RAM usage: 1 bytes (1 local), 255 bytes free
; Maximum call level: 0
; Codepage 0 has 15 word(s) : 0 %
; Codepage 1 has 0 word(s) : 0 %
; Total of 15 code words (0 %)
Hola Picuino. Que madrugón para empezar a contestar ((:-)) ((:-))
0149 0872 MOVF i, W
014A 00F1 MOVWF 0x71
014B 3001 MOVLW 0x1
014C 35F1 LSLF 0x71, F
014D 3EFF ADDLW 0xFF
014E 1D03 BTFSS STATUS, 0x2
014F 294C GOTO 0x14C
0150 3571 LSLF 0x71, W
0151 3E20 ADDLW 0x20
0152 0086 MOVWF FSR1
0153 0187 CLRF FSR1H
0154 0020 MOVLB 0x0
0155 0840 MOVF keyb, W
0156 3FC0 MOVWI [0]FSR1
0157 0841 MOVF 0x41, W
0158 3FC1 MOVWI [1]FSR1
0159 0842 MOVF 0x42, W
015A 3FC2 MOVWI [2]FSR1
015B 0843 MOVF 0x43, W
015C 3FC3 MOVWI [3]FSR1
unsigned char b; // b es una variable de 8 bits sin signo
b = 0b11001100; // Ahora b vale 11001100 (en binario)
b |= 0b00100000; // Ahora he hecho un OR con el bit 5 a uno y la variable vale 0b11101100
b |= (1<<5); // Lo mismo que antes. El número 0b00100000 lo he creado desplazando un uno hacia la izquierda 5 veces
b &= 0b11011111; // Ahora he hecho un AND con el bit 5 a cero y la variable vale otra vez 0b11001100
b &= ~(1<<5); // Lo mismo que antes, desplazando un uno cinco veces a la izquierda, y por último se invierte el numero (operación ~)
//
// Lo mismo de antes un poco más fácil:
//
b = 0b11001100; // Ahora b vale 11001100 (en binario)
b = b | 0b00100000; // Ahora he hecho un OR con el bit 5 a uno y la variable vale 0b11101100
b = b | (1<<5); // Lo mismo que antes. El número 0b00100000 lo he creado desplazando un uno hacia la izquierda 5 veces
b = b & 0b11011111; // Ahora he hecho un AND con el bit 5 a cero y la variable vale otra vez 0b11001100
b = b & ~(1<<5); // Lo mismo que antes, desplazando un uno cinco veces a la izquierda, y por último se invierte el numero (operación ~)
b &= ~(1<<5);
Lo que no e podido hacer es el manejo de un solo bit dentro de una variable, ya sea setearlo, borrarlo o comprobarlo, pero bueno, seguiré intentando.
Con respecto al microcontrolador 16F1719, ya he leído anteriormente que en Argentina hay problemas con las importaciones.
He encontrado el micro en Mouser Argentina:
http://ar.mouser.com/ProductDetail/Microchip-Technology/PIC16F1719-I-PT/?qs=sGAEpiMZZMvqv2n3s2xjsZgUB1jPAEqBP9PrLuWOhpXtotz6TvrcXQ%3d%3d
¿También en este caso hay problemas de suministro?
hay otra técnica pero no puedo acordarme el nombre, seguro los muchachos lo van a agregar.
Bit-banding: Maps a complete word of memory onto a single bit in the bit-band region. For example, writing to an alias word will set or clear the corresponding bit in the bitband region. This allows every individual bit in the bit-banding region to be directly accessible from a word-aligned address, and individual bits to be toggled from C/C++ without performing a read-modify-write sequence of instructions
struct {
unsigned flag0:1;
unsigned flag1:1;
unsigned flag2:1;
unsigned flag3:1;
unsigned flag4:1;
unsigned flag5:1;
unsigned flag6:1;
unsigned flag7:1;
} variable;
void main(void) {
variable.flag5 = 0;
}
union {
unsigned char byte;
struct {
unsigned flag0:1;
unsigned flag1:1;
unsigned flag2:1;
unsigned flag3:1;
unsigned flag4:1;
unsigned flag5:1;
unsigned flag6:1;
unsigned flag7:1;
};
} variable;
void main(void) {
variable.byte = 0b11001100;
variable.flag5 = 0;
}
Entiendo que no existe mouser en Argentina, es solo un sitio web (el .ar), pero físicamente no tienen almacenes en Argentina.
El representante odicial de Microchip es Elemon y la unica forma de que traigan algo como eso es comprarles un reel entero...
Entiendo que no existe mouser en Argentina, es solo un sitio web (el .ar), pero físicamente no tienen almacenes en Argentina.
El representante odicial de Microchip es Elemon y la unica forma de que traigan algo como eso es comprarles un reel entero...
He visto que en la web de Elemon hay varios micros modernos de la serie PIC16 (PIC16F17xx, PIC16F18xx, etc)
La mayoría de esos micros necesitan para programarlos el compilador XC8 y el IDE MPLAB X, de manera que estas son las mejores opciones para comenzar, puesto que tienen más futuro y dan soporte a más micros.
Un saludo.
Hola elgarbe, Picuino y KILLERJC, gracias por los aportes, son todos de mucha utilidad (por lo menos para mí), pero temo que me e expresado mal cuando me e referido a "manejo de bit's", en realidad, lo que yo quería decir es a comprobar un bit dentro de un byte, algo así a la funciónes btfsc/btfss del .asm, pero por supuesto en el C y para con el dato en cuestión poder usar la función "if" del C.
if ( var & 0x08 ) {
Si el resultado de la operacion "var & 0x08" es 0 no va a entrar aca
Si esta en un 1 ese bit va a entrar aca
}Hola elgarbe, Picuino y KILLERJC, gracias por los aportes, son todos de mucha utilidad (por lo menos para mí), pero temo que me e expresado mal cuando me e referido a "manejo de bit's", en realidad, lo que yo quería decir es a comprobar un bit dentro de un byte, algo así a la funciónes btfsc/btfss del .asm, pero por supuesto en el C y para con el dato en cuestión poder usar la función "if" del C.
Ahora si nos entendemos xD, estoy con que esto deberia funcionar. Aunque uno espera una resultado booleano 1 (true ) o 0 (false), creo que se basa unicamente en la deteccion del 0, por lo tanto no varia si es 1,8 o 15 para tomarlo como true.Código: [Seleccionar]if ( var & 0x08 ) {
Si el resultado de la operacion "var & 0x08" es 0 no va a entrar aca
Si esta en un 1 ese bit va a entrar aca
}
Aclaracion, si eso no funciona, podria ser ((var & 0x08) == 0) o != 0, pero creo que deberia funcionar sin el condicional.
Que esto se reemplaze en un simple BTFSS/BTFSC ahi lo veo complejo.
Podes usar un #define FLAG_ALGO 0x08, asi queda mas claro y entendible el codigo. quedandote ( var & FLAG_ALGO )
Igual eso es para una variable, en los registros tenes definidos los bits y quedaria por ejemplo
if ( INTCONbit.TXIF ) { }
Y si quisieras que sea una logica negada es decir que entre cuando este en 0 al if, le antepones el ! , quedando if ( !INTCONbits.TXIF ) , lo mismo podes hacer con la variable, este si creo que se reemplazaria correctamente en ASM, pero bueno, son las contras del C.
Código: [Seleccionar]if ( var & 0x08 ) {
Si el resultado de la operacion "var & 0x08" es 0 no va a entrar aca
Si esta en un 1 ese bit va a entrar aca
}
Aclaracion, si eso no funciona, podria ser ((var & 0x08) == 0) o != 0, pero creo que deberia funcionar sin el condicional.
Que esto se reemplaze en un simple BTFSS/BTFSC ahi lo veo complejo.
Picuino, por supuesto que no andaba buscando el reemplazo exacto de esas funciones del .asm, pero si tu dices que llegan a ese nivel, pues mejor todavía.
Hola gente, así da gusto aprender. Picuino, por supuesto que no andaba buscando el reemplazo exacto de esas funciones del .asm, pero si tu dices que llegan a ese nivel, pues mejor todavía.
elgarbe, muy bueno ese link, ya lo e agendado para tenerlo a mano. Gracias
if ( condición ) { true ;
} else { false ;
} ;
A ver si entendí correctamente la función "if", si condición es 1 o superior realiza la operación en TRUE, y si es cero realiza lo ubicado en FALSE. ¿Esto es así?
Por lo tanto si lo anterior es correcto, dentro de "condición" no es obligatorio usar una función matemática, con que tenga una variable es suficiente. ¿Es esto correcto o me equivoco?
Muchas gracias a todos por la enseñanza y sobre todo por la paciencia. Un saludo.
Atte. CARLOS.
Así es, y como eso de que con algo mayor a 1 tambien es conciderado TRUE es un arma de doble ya que con algún error o descuido podemos entrar como condicion verdadera algo que no lo es, se suele hacer:
#DEFINE TRUE 1
#DEFINE FALSE 0
#DEFINE PIN_LED (1<<5)
if ( (PORTB & PIN_LED) == TRUE) { }
Si bien son más "caracteres" escritos, se evitan algun posible error. No sé si es buena práctica lo que pongo acá, simplemente comentar que lo he visto en muchos programas "grandes"
Saludos!
En la condicion del if, lo que realmente vale la pena mirar es PORTB & PIN_LED, Si vos te equivocas en eso o metes un error en eso el "== TRUE" no te va a salvar para nada. Miremos las 2 posibilidades
True == True -> True
False == True -> False
si la condicion que dije es True, el resultado es True. Si la condicion es False, el resultado tambien es False. No evitaria ningun error o un descuido por que pusiste mal el valor PIN o el PORT.
Yo siempre uso en .asm una pequeña rutina para manejar los LCD's, la e realizado en XC8 y si bien es más fácil y rápida de comprender, incluso de programar, la contra es que en .asm me ocupaba solo 180 posiciones de memoria de programa y en XC8 me ocupa 290, una diferencia importante.
Pero bueno, es un precio bajo a pagar (si logro llegar a manejar bien el C) por la comodidad y velocidad de programación.
void lcd_puts(char *string) {
while(*string != 0) {
LCD_DATO(*string);
string++;
}
void main(void) {
char mensaje[] = "Hola Mundo";
lcd_puts(mensaje);
}
#ifndef __LCD_H
#define __LCD_H
#define LCD_RS PORTBbits.RB0
#define LCD_E PORTBbits.RB1
#define LCD_D4 PORTBbits.RB2
#define LCD_D5 PORTBbits.RB3
#define LCD_D6 PORTBbits.RB4
#define LCD_D7 PORTBbits.RB5
void LCD_INICIALIZAR(void);
void LCD_IN(unsigned char);
void LCD_INST(unsigned char);
void SACAR(unsigned char);
void LCD_DATO(unsigned char);
#endif
#include "lcd.h"
// Resto del programa con las funciones de tratamiento del lcd ...
// En este archivo no se coloca la rutina main
#include "lcd.h"
// Programa que va a utilizar el LCD (rutina main)
void main(void) {
//...
}
Las definiciones de las funciones se escriben en un archivo separado con extensión *.h (header)
De esta forma, se puede acceder a las definiciones de las funciones en el caso de utilizar una librería y que el código c no sea accesible
Si bien el programa en .asm estaba bastante optimizado, creo que en C le falta mucho para estarlo, funciona, pero de seguro hay muchas cosas para mejorarle.