Hoola!
La tarjeta Xprees tiene integrado un sensor de temperatura I2C, es el modelo EMC1001, de este sensor leeremos la temperatura por I2C y la transmitiremos por UART
Lo primero que tenemos que hacer es un proyecto nuevo en el MPLABX (Ctrl+Mayus+N) y abrir el MCC, una ves ahí agregamos el modulo de EUSART y activamos la opción de Redirect STDIO to USART
Para poder agregar el modulo de MSSP1 primero tendemos que cambiar el Core del MCC, lo tenemos que degradar a la versión 4.55, 4.56 o 4.65, que es la ultima que tiene la librería con las cuales me enseñaron a trabajar y con las cuales Microchip puso sus ejemplos, futuras versiones, la librería es un poco mas compleja, pera los valientes que se quieran adentrar a utilizar la nueva librería (o me puedan pasar documentación de donde hablen detalladamente de esta y pongan ejemplos, se los agradecería)
Para hacer el cambio de Core, nos vamos a la parte inferior izquierda y ubicamos la ventana de versiones del MCC, y desplegamos la lista de Cores, después en la lista buscamos alguna de las 3 versiones que les había comentado anteriormente y la palomeamos para que se hagan los cambios necesarios
Si a la hora de hacer el cambio de Core, les aparece este dialogo, le dan en YES
Una vez hecho el cambio de Core, ahora si podemos seleccionar el periférico MSSP1 [Pic10/...]
Notas de lo que configuramos:
Mode: Como es que queremos que se comporte nuestro modulo, puede ser como I2C o SPI, tanto como modo esclavo, como modo maestro
MS Bus, es otro protocolo de comunicación que abarca I2C, si habilitamos este, es para hacer compatibles los niveles de voltaje
Slew rate control: el Slew rate es que tan rapido puede cambiar una señal de 1 a 0, o viceversa, esto hace que se realentice el cambio de estado, para evitar el ruido tipo emi, por ejemplo
https://www.electrical4u.com/slew-rate/
SDA hold time: es un parámetro del protocolo I2C, es un tipo delay para que la linea de clock espere el flanco
Baud rate generator: es un timer dedicado especialmente para I2C, depende el valor que le carguemos, será la velocidad de clock que se genere, esto depende directamente del valor del clock del sistema
El pin Manager debe quedar de la siguiente manera:
Generamos y cerramos el MCC
Ya en el código, ya que el I2C utiliza interrupciones, necesitamos habilitar las interrupciones globales y las de periféricos
Después, tendremos que crear una función que nos genere los TRB'S (Transaction Request Block), esta función devolverá un valor de 8 bits que es el estatus (unit8_t), esta función la utilizarememos tanto como para leer, como para escribir
Después escribiremos I2C y con las teclas CTRL + Espacio, nos aparecerá una lista para autocompletar con los resultados, ahí seleccionamos la de I2C1_MESSAGE_STATUS
Necesito realizar 2 transacciones, una para decirle al esclavo que necesito leer y la segunda para ya leer es por eso que el arreglo trb tiene un 2
Ahora vamos a preparar los bloques de transacciones, primero será el de envió, con la línea de código I2C1_MasterWriteTRBBuild(), que nos pedirá los siguientes parámetros:
I2C1_TRANSACTION_REQUEST_BLOCK *ptrb: es un puntero de nuestra transacción, le ponemos el & para que le pase la dirección de memoria. &trb[0]
uint8_t *pdata: es puntero al registro que quiero escribir del sensor. ®istro
uint8_t length: es la longitud de lo que quiero escribir. 1
uint16_t address: es la Address del esclavo al que me quiero referir
Y después la de I2C1_MasterReadTRBBuild(), que nos pedirá casi los mismos parámetros
I2C1_TRANSACTION_REQUEST_BLOCK *ptrb: es un puntero de nuestra transacción, le ponemos el & para que le pase la dirección de memoria. &trb[1]
uint8_t *pdata: es puntero al registro que quiero escribir del sensor. ®istro
uint8_t length: es la longitud de lo que quiero leer. 1
uint16_t address: es la Address del esclavo al que me quiero referir
Por ultimo tenemos que poner los bloques en una función que los ponga en la cola de transacciones, esto se hace con I2C1_MasterTRBInsert(), donde le tenemos que pasar los parámetros:
uint8_t count: la cantidad de transacciones a realizar, en esta caso 2
I2C1_TRANSACTION_REQUEST_BLOCK *ptrb_list: un puntero a donde inicia mi lista de transacciones
I2C1_MESSAGE_STATUS *pflag: el puntero de la bandera de status
Mientras que siga pendiente, nos vamos a esperar a que termine la transacción y después podemos regresar un 1 si el mensaje se completo, que esto se realiza en las ultimas 2 líneas de código
Ya terminada nuestra función para enviar paquetes, ahora nos podemos mover al main.c
Lo primero que tenemos que hacer es declarar 2 variables, para guardar la temperatura, la parte alta de la temperatura es sensible a los valores negativos, es por eso que es signed, mientras que la parte baja, no. Esto porque así esta en la datasheet del sensor
Dado que nuestra función TRB tiene un valor de retorno, lo podemos evaluar, el primer parámetro es al registro al que queremos apuntar, en este caso 0x00, para obtener el High byte de la temperatura, el segundo parámetro, es el puntero a donde yo quiero guardar que me devolvió el sensor y dado que las variables no están declaradas como puntero, le ponemos el & para que pase la dirección de la memoria; tenemos que castear de signed a unsigned, que es lo que espera la función, solo para el pase de parámetro agregamos (uint8_t*) *para forzarla a puntero
La función del if se va a ejecutar si el TRB regresa un verdadero
Si sale bien, otra ves podemos llamar de nuevo a la función TRB para solicitar la parte baja de la temperatura que esta en el registro 0x02, como la parte baja se nos entrega justificada a la izquierda, hacemos un corrimiento de 6 hacia la derecha, para que ya la podamos leer mejor (de estar así 11000000 >> pasa a 00000011)
Ahora solo queda jugar con la información ya guardada en nuestras variables, primero preguntamos si nuestra parte alta es menor que cero, es decir es negativa, si así es tenemos que aplicarle un completo a 2, existen varias formas de hacerlo, yo deje comentada una segunda forma de como hacerlo en el código; pero en resumidas cuentas lo que es el complemento a 2 es cambiar todos los 1s por 0s y viceversa y al final sumar un 1 y listo, esa es la forma mas fácil de obtenerlo
Finalmente para imprimir los datos, utilizaremos un printf donde %d es un entero decimal con signo, \n es nueva línea hacia abajo, y \r es retorno de carro (volver a la columna 1 del texto), y esperamos un segundo antes de que se repita otra vez todo el código
Por si se perdieron con las imágenes y los comentarios de los pasos, aquí les dejo el Main
Finalmente, compilamos en el martillo con escobita, lo subimos a la Xpress board, abrimos Teraterm, y deberíamos de estar recibiendo la temperatura ambiente que esta al rededor del sensor
Extra, para los que quieran ver como acceder a otros registros del sistema, en este código y ejemplo les dejo como acceder
Comments