Tengo este código en C# y quiero hacer lo mismo en Java modo consola. Lo que hace es introducir 16 números o dígitos binarios, es decir, solo puedes introducir 1 y 0 hasta 16, pulsa enter y muestra los resultados en hexadecimal.
Código
usingSystem;
usingSystem.Linq;
namespace Binario_cs
{
class Program
{
staticvoid Main(string[] args)
{
// Título de la ventana.
Console.Title="Binaro a ensamblador de PIC16F84A - C#";
// Muestra texto en pantalla pidiendo que introduzca los datos en binario.
Tutorial Arduino Consola y puerto serie. Interfaz creado con diversos lenguajes como C#, C++ CLR y VB .net bajo Visual Studio Community que puedes controlar el puerto serie a Arduino encendiendo y apagando un Led, manejar el LCD y recibes mensajes hacia el ordenador o PC.
En este apartado mostramos el código fuente en C#, en el PDF se encuentra C#, C++ CLR y VB .net.
Código C#:
Código:
using System; using System.IO.Ports; using System.Text;
namespace Arduino_Consola_cs { class Program { static void Main(string[] args) { // Título de la ventana. Console.Title = "Arduino Consola C#";
// Establecer los tiempos de espera de lectura / escritura. Puerto_serie.ReadTimeout = 500; // Milisegundos. Puerto_serie.WriteTimeout = 500;
// Detecta cualquier dato recibido. Puerto_serie.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
Puerto_serie.Open(); // Abrir puerto.
ConsoleKey tecla; Console.WriteLine("Pulse tecla 1 para encender y 2 para apagar:");
do { tecla = Console.ReadKey(true).Key; // Espera pulsación de teclas.
switch (tecla) { case ConsoleKey.D1: // Tecla 1 del teclado estandar. case ConsoleKey.NumPad1: // Tecla 1 del número del pad. byte[] miBuffer1 = Encoding.ASCII.GetBytes("Luz_ON"); // Codificación ASCII y guarda en la variable array tipo byte. Puerto_serie.Write(miBuffer1, 0, miBuffer1.Length); // Envía los datos del buffer todo su contenido. Console.WriteLine("Comando \"Luz_ON\" enviado."); // Muestra en pantalla comandos enviado. break;
case ConsoleKey.D2: case ConsoleKey.NumPad2: byte[] miBuffer2 = Encoding.ASCII.GetBytes("Luz_OFF"); Puerto_serie.Write(miBuffer2, 0, miBuffer2.Length); Console.WriteLine("Comando \"Luz_OFF\" enviado."); break;
default: Console.WriteLine("Tecla el 1, el 2 y Escape para salir."); break; } } while (tecla != ConsoleKey.Escape); // Pulsa Escape para salir del menú.
Console.WriteLine("Presione cualquier tecla para terminar..."); Console.WriteLine(); Console.ReadKey(); // Espera pulsar una tecla cualquiera. Puerto_serie.Close(); // Cierra el puerto serie. }
// Detecta cualquier dato entrante. private static void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e) { SerialPort sp = (SerialPort)sender; string entradaDatos = sp.ReadExisting(); // Almacena los datos recibidos en la variable tipo string. Console.WriteLine("Dato recibido desde Arduino: " + entradaDatos); // Muestra en pantalla los datos recibidos. } } }
Código C# Avanzado:
Código:
using System; using System.IO; using System.IO.Ports; using System.Text; using System.Speech.Recognition; // No olvidar. Micro. using System.Speech.Synthesis; // No olvidar. Altavoz.
namespace Arduino_Consola_Color_Voz_cs { class Program { static void Main(string[] args) { string COM = "";
// Título de la ventana. Console.Title = "Arduino Consola color y voz C#";
// Crear un nuevo objeto SerialPort con la configuración predeterminada. Puerto_serie = new SerialPort();
// Configuración. Console.Write(@" Introduzca un número para seleccionar puerto COM. Por ejemplo el 4, sería COM4.
Puerto: "); COM = Console.ReadLine(); // Escribir el número del puerto. Console.Clear();
Puerto_serie.PortName = "COM" + COM; // Número del puerto serie.
Puerto_serie.BaudRate = 115200; // Baudios. Puerto_serie.Parity = Parity.None; // Paridad. Puerto_serie.DataBits = 8; // Bits de datos. Puerto_serie.StopBits = StopBits.Two; // Bits de parada. Puerto_serie.Handshake = Handshake.None; // Control de flujo.
// Establecer la lectura / escritura de los tiempos de espera. Puerto_serie.ReadTimeout = 500; Puerto_serie.WriteTimeout = 500;
try { Puerto_serie.Open(); // Abrir el puerto serie. }
catch (IOException) { Console.ForegroundColor = ConsoleColor.Red; // Texto en rojo. Console.CursorVisible = false; Console.SetCursorPosition(16, 6); Console.WriteLine(@"El puerto " + Puerto_serie.PortName + @" no existe o no lo encuentra."); Console.ReadKey(); // Pulse cualquier tecla. Environment.Exit(1); // Salir de la aplicación. }
// Detecta cualquier dato recibido. Puerto_serie.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
ConsoleKey tecla; Console.WriteLine("Pulse tecla 1 para encender, 2 para apagar y \n" + "Escape para salir. \n" + "--------------------------------------------------------------\n");
do { tecla = Console.ReadKey(true).Key; // Espera pulsación de teclas. // Inicializar una nueva instancia de SpeechSynthesizer. using (SpeechSynthesizer altavoz = new SpeechSynthesizer()) { // Configure la salida de audio. altavoz.SetOutputToDefaultAudioDevice();
// Velocidad de la voz. altavoz.Rate = -2; // Valores entre -10 a 10.
// Volumen de la voz. altavoz.Volume = 100; // Valores entre 0 y 100.
switch (tecla) { case ConsoleKey.D1: // Tecla 1 del teclado estandar. case ConsoleKey.NumPad1: // Tecla 1 del número del pad. byte[] miBuffer1 = Encoding.ASCII.GetBytes("Luz_ON"); // Codificación ASCII y guarda en la variable array tipo byte. Puerto_serie.Write(miBuffer1, 0, miBuffer1.Length); // Envía los datos del buffer todo su contenido. Console.ForegroundColor = ConsoleColor.Gray; Console.Write("Comando"); // Muestra en pantalla comandos enviado. Console.ForegroundColor = ConsoleColor.Green; Console.Write(" \"Luz_ON\" "); Console.ForegroundColor = ConsoleColor.Gray; Console.WriteLine("enviado."); Console.ForegroundColor = ConsoleColor.Gray; altavoz.Speak("Luz encendida."); break;
case ConsoleKey.Escape: Console.WriteLine("Saliendo..."); altavoz.Speak("Saliendo."); break;
default: Console.WriteLine("Tecla el 1, el 2 y Escape para salir."); break; } } } while (tecla != ConsoleKey.Escape); // Pulsa Escape para salir del menú.
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine(); Console.WriteLine("╔═════════════════════════════════════════════════════╗"); Console.WriteLine("║ Electrónica PIC metaconta@gmail.com ║"); Console.WriteLine("║ ║"); Console.WriteLine("║ Ángel Acaymo M. G. ║"); Console.WriteLine("╚═════════════════════════════════════════════════════╝"); Console.WriteLine();
Console.ForegroundColor = ConsoleColor.Cyan; Console.WriteLine("Pulse cualquier tecla para salir..."); Console.WriteLine(); Console.ReadKey(); // Espera pulsar una tecla cualquiera. Puerto_serie.Close(); // Cierra el puerto serie. }
// Detecta cualquier dato entrante. private static void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e) { SerialPort sp = (SerialPort)sender; string entradaDatos = sp.ReadExisting(); // Almacena los datos recibidos en la variable tipo string. Console.ForegroundColor = ConsoleColor.Gray; Console.Write("Dato recibido desde Arduino: "); // Muestra en pantalla los datos recibidos. Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine(entradaDatos + "\n"); Console.ForegroundColor = ConsoleColor.Gray; }
// ----- Electrónica PIC ----- // // Ejercicio 2. // // Encendido y apagado del Led 13 mediante puerto serie con pantalla. // Es lo mismo que el Ejercicoi 1, pero usando el LCD Keypad Shield.
// Pin 10 para saber que es luz de fondo. const byte LuzFondo = 10;
const byte Led = 13; // Declaramos la variable pin del Led. char caracter; String comando;
void setup() { pinMode(Led, OUTPUT); // Inicializa el pin del LED como salida: Serial.begin(115200); // Puerto serie 115200 baudios. lcd.begin(16, 2); // Formato de pantalla. lcd.clear(); // Borra la pantalla y su posición superior izquierda. lcd.print(" Arduino "); delay(1000); }
void loop() { /* Voy leyendo carácter a carácter lo que se recibe por el canal serie (mientras llegue algún dato allí), y los voy concatenando uno tras otro en una cadena. En la práctica, si usamos el "Serial monitor" el bucle while acabará cuando pulsamos Enter. El delay es conveniente para no saturar el canal serie y que la concatenación se haga de forma ordenada. */ while (Serial.available() > 0) { caracter = Serial.read(); comando.concat(caracter); delay(10); }
/* Una vez ya tengo la cadena "acabada", compruebo su valor y hago que la placa Arduino reacciones según sea este. Aquí podríamos hacer lo que quisiéramos: si el comando es "tal", enciende un Led, si es cual, mueve un motor... y así. */
// Si los carácteres es recibido y verdadero. if (comando.equals("Luz_ON") == true) { digitalWrite(Led, HIGH); // Enciende el Led 13. Serial.write("ON - Led encendido."); // Envía este mensaje al PC. lcd.setCursor(0, 1); lcd.print("Luz ON. "); // Mostrar en el LCD. }
if (comando.equals("Luz_OFF") == true) { digitalWrite(Led, LOW); // Apaga el Led 13. Serial.write("OFF - Led apagado. "); // Envía este mensaje al PC. lcd.setCursor(0, 1); lcd.print("Luz OFF. "); // Mostrar en el LCD. }
// Limpiamos la cadena para volver a recibir el siguiente comando. comando = ""; }
El archivo p16f84a.inc que encuentras en el directorio en mi caso cuando instalé MPLAB X v4.00. C:\Program Files (x86)\Microchip\MPLABX\v4.00\mpasmx
p16f84aa.inc:
Código:
LIST
;========================================================================== ; Build date : May 17 2017 ; MPASM PIC16F84A processor include ; ; (c) Copyright 1999-2017 Microchip Technology, All rights reserved ;==========================================================================
NOLIST
;========================================================================== ; This header file defines configurations, registers, and other useful ; bits of information for the PIC16F84A microcontroller. These names ; are taken to match the data sheets as closely as possible. ; ; Note that the processor must be selected before this file is included. ; The processor may be selected the following ways: ; ; 1. Command line switch: ; C:\MPASM MYFILE.ASM /PIC16F84A ; 2. LIST directive in the source file ; LIST P=PIC16F84A ; 3. Processor Type entry in the MPASM full-screen interface ; 4. Setting the processor in the MPLAB Project Dialog ;==========================================================================
Elegimos la F que corresponde guardar en el propio registro, es un 1. La d es el lugar de destino, W que equivale a 0 se guarda en el registro de trabajo. La F que equivale a 1 se guarda en el registro.
En resumen: MOVFPORTB, F
MOVFH'0006', H'0001'
000010001000 0110
Pseudocódigo de nuestro compañero del foro explorer:
Código:
bits1413 = (0b11_0000_0000_0000 & opcode) >> 12; // extraemos los dos bits superiores
switch (bits1413) { case 0b00: // en este caso, el tercer nibble es la operación, el bit 7 es la suboperación o destino, y el resto, el operando nibble3 = (0b00_1111_0000_0000 & opcode) >> 8; bit7 = (0b00_0000_1000_0000 & opcode) >> 7; operando = (0b00_0000_0111_1111 & opcode);
switch (bit7) { case 0: reg = 'W'; break; case 1; reg = 'F'; break; }
switch (nibble3) {
case 0x0: switch (bit7) { case 1: printf("MOVWF %x\n", operando); break; case 0; // aquí pueden ocurrir varios casos, según el primer nibble nibble1 = (0b00_0000_0000_1111 & opcode); switch (nibble1) { case 0x0: printf("NOP\n"); break; case 0x4: printf("CLRWDT\n"); break; case 0x9: printf("RETFIE\n"); break; case 0x8: printf("RETURN\n"); break; case 0x3: printf("SLEEP\n"); break; } break; } break; case 0x1: switch (bit7) { case 0: printf("CLRW\n"); break; case 1; printf("CLRF %x\n", operando); break; } break; case 0x2: printf("SUBWF %x,%c\n", operando, reg); break; case 0x3: printf("DECF %x,%c\n", operando, reg); break; case 0x4: printf("IORWF %x,%c\n", operando, reg); break; case 0x5: printf("ANDWF %x,%c\n", operando, reg); break; case 0x6: printf("XORWF %x,%c\n", operando, reg); break; case 0x7: printf("ADDWF %x,%c\n", operando, reg); break; case 0x8: printf("MOVF %x,%c\n", operando, reg); break; case 0x9: printf("COMF %x,%c\n", operando, reg); break; case 0xA: printf("INCF %x,%c\n", operando, reg); break; case 0xB: printf("DECFSZ %x,%c\n", operando, reg); break; case 0xC: printf("RRF %x,%c\n", operando, reg); break; case 0xD: printf("RLF %x,%c\n", operando, reg); break; case 0xE: printf("SWAPF %x,%c\n", operando, reg); break; case 0xF: printf("INCFSZ %x,%c\n", operando, reg); break; } break; case 0b01: // en este caso, los bits 12 y 11 es la suboperación, los bits 8, 9 y 10 es el número de bit, y el resto, el operando subop = (0b00_1100_0000_0000 & opcode) >> 10; bit = (0b00_0011_1000_0000 & opcode) >> 7; operando = (0b00_0000_0111_1111 & opcode);
switch (subop) { case 0x0; printf("BCF %x,%d\n", operando, bit); break; case 0x1; printf("BSF %x,%d\n", operando, bit); break; case 0x2; printf("BTFSC %x,%d\n", operando, bit); break; case 0x3; printf("BTFSS %x,%d\n", operando, bit); break; } break; case 0b10: // ver el bit 12. El resto es el operando bit12 = (0b00_1000_0000_0000 & opcode) >> 11; operando = (0b00_0111_1111_1111 & opcode);
switch (bit12) { case 0: printf("CALL %x\n", operando); break; case 1: printf("GOTO %x\n", operando); break; } break; case 0b11: // el tercer nibble es la suboperación, y el resto, el operando nibble3 = (0b00_1111_0000_0000 & opcode) >> 8; operando = (0b00_0000_1111_1111 & opcode);
switch (nibble3) { case 0b0000: case 0b0001: case 0b0010: case 0b0011: printf("MOVLW %x\n", operando); break; case 0b0100: case 0b0101: case 0b0110: case 0b0111: printf("RETLW %x\n", operando); break; case 0b1000: printf("IORLW %x\n", operando); break; case 0b1001: printf("ANDLW %x\n", operando); break; case 0b1010: printf("XORLW %x\n", operando); break; case 0b1100: case 0b1101: printf("SUBLW %x\n", operando); break; case 0b1110: case 0b1111: printf("ADDLW %x\n", operando); break; } break; }
Yo y un amigo lo valos a traducir por el momento a Java que es el que entiende mejor, luego haré en otros lenguajes para quien le guste, como dije arriba, C#, C++ CLR y VB .net.
Tanto decir que puede abrir el archivo upg y nada. Hay otro método para tener los datos.
1. Identificar la EEPROM o EEPROMs que pueda tener el Televisor. 2. Usar herramientas para leer la EEPROM y guardar el archivo en el escritoroi de Windows o donde quieras. Los archivos suelen ser .hex o .bin. Las herramientas más usadas son Willem Programmer y el Mini Pro TL866A.
Y cuando falle la EEPROM que suele pasar muchos en TV, que dicen mi TV ha muerto, ese es uno de los motivos.
Usé el programa vertsión del 2015 de File View Pro, que tanto aseguran abrir el archivo extensión upg. La verdad me lo abre tal como lo hace el editor hexadecimal H&D.
Menuda broma, y eso que llevo mucho tiempo averiaguando como se abre.
Hice esto, funciona pero no se si es el más adecuado hacerlo de esta manera, me siento que hice chapuza.
Código
@Echo OFF
title Arduino CMD y puerto serie
CHCP 1252>Nul
MODE.com COM4 BAUD=115200PARITY=n DATA=8STOP=1
:Menu
CLS
echo.
echo.
echo. 1.- Luz ON
echo.
echo. 2.- Luz OFF
echo.
echo. 3.- Salir
echo.
echo.
echo.
CHOICE.exe /C "123"/M " Escoge una opción "
echo.
echo.
echo.
If %ErrorLevel% EQU 1(
copy puerto_Luz_ON.txt COM4:
echo Puerto COM4: Luz ON
timeout 1>nul
goto Menu
)
If %ErrorLevel% EQU 2(
copy puerto_Luz_OFF.txt COM4:
echo Puerto COM4: Luz OFF
timeout 1>nul
goto Menu
)
Pause
Exit /B
Hay otra cosa que no se como se hace.
A la hora de recibir datos por el puerto serie. ¿Cómo se hace?
Lo comento porque cada vez que envío al puerto serie Luz_ON, desde el puerto serie me devuelve Luz encendido. Este mensaje tiene que mostrarse en pantalla.
La mejor opción para enviar datos al puerto serie y funciona bien es este código:
Código
@Echo OFF &(CHCP 1252)1>Nul
MODE.com COM4 BAUD=115200PARITY=n DATA=8STOP=1
CHOICE.exe /C "12"/M "Escoge una opción..."
If %ErrorLevel% EQU 1(
copy puerto_Luz_ON.txt COM4:
)
If %ErrorLevel% EQU 2(
copy puerto_Luz_OFF.txt COM4:
)
Pause & Exit
Hay un problemilla. Si pulso la tecla 1 o la tecla 2 para enviar datos, se cierra el CMD. Debería dejarte pulsar las teclas 1 y 2 siempre, no que pulse una tecla y se cierra.
Centrándome en el .cmd, o lo que es lo mismio, el .bat, no funciona el código:
Código
@Echo OFF &(CHCP 1252)1>Nul
MODE.com COM4 BAUD=115200PARITY=n DATA=8STOP=1
CHOICE.exe /C "12"/M "Escoge una opción..."
If %ErrorLevel% EQU 1(
Echo:Luz_ON>COM4
)
If %ErrorLevel% EQU 2(
Echo:Luz_OFF>COM4
)
Pause&Exit
Lo que he hecho es hacer guardar hacer dos archivos, uno llamado puerto_Luz_ON.txt y el otro llamado puerto_Luz_OFF.txt. En el puerto_Luz_ON.txt tiene solo el texto Luz_ON y el otro Luz_OFF de los txt.
Luego en el cmd puse:
Código
copy puerto_Luz_ON.txt COM4:
Ya me funciona, he enviado Luz_ON que está en el interior del archivo puerto_Luz_ON.txt.
Modificando el Scrip.cmd de arriba lo he hecho funcionar así:
Código
@Echo OFF &(CHCP 1252)1>Nul
MODE.com COM4 BAUD=115200PARITY=n DATA=8STOP=1
CHOICE.exe /C "12"/M "Escoge una opción..."
If %ErrorLevel% EQU 1(
copy puerto_Luz_ON.txt COM4:
)
If %ErrorLevel% EQU 2(
copy puerto_Luz_OFF.txt COM4:
)
Pause&Exit
Lo que no me hace gracia es que tengo que crear dos archivos .txt al lado del Script.cmd. La idea es tener todo en un solo archivo .cmd. Para eso se podría que no se si se puede, el Script.cmd crear los dos archivos .txt y su contenido Luz_ON y Luz_OFF. Poco a poco va tomando forma.
Datos de interés, el modo más rápido y abreviado frente a este:
Código
MODE.com COM4 BAUD=115200PARITY=n DATA=8STOP=1
Es este:
Código
MODE COM4:115200,n,8,1
En cuanto hacer el control del puerto serie con F#, no tiene que ver con C#, su codigo en C# si lo tengo hecho.
Código
usingSystem;
usingSystem.IO.Ports;
usingSystem.Text;
namespace Arduino_Consola_cs
{
class Program
{
staticvoid Main(string[] args)
{
// Título de la ventana.
Console.Title="Arduino Consola C#";
// Tamaño ventana consola.
Console.WindowWidth=55;// X. Ancho.
Console.WindowHeight=18;// Y. Alto.
// Cree un nuevo objeto SerialPort con la configuración predeterminada.