Reloj Digital con Displays de 7 Segmentos y PIC 16F84A
En esta oportunidad quiero compartir con ustedes un sencillo reloj basado en un
Microcontrolador PIC de la serie 16F84A y usando display nodo comn de 7 segmentos.
Adicionalmente usa otros circuitos con la finalidad de expander el nmero de salidas, tanto para control como para datos, y de esa forma podemos contar con ms displays y ms opciones de Configuracin. Entre estos circuitos tenemos el conocido 74LS47, de cul dejar el esquema mostrando la disposicin de sus pines (Figura 1), as como su tabla de verdad (Figura 2). Para mayor informacin pueden consultar el datasheet de este componente.
Disposicin de pines
Tabla de Verdad
Otro circuit usado es el 74LS138, el cul funcionar como selector de display para realizar el efecto de barrido. No detallar tampoco a este componente puesto que no es el objetivo de este post, pero si dejar algunas imgenes, que al igual que las anteriores, nos da una vista rpida de la disposicin y el funcionamiento de este integrado.
Disposicin de pines
Tabla de Verdad
Tambin dejar el diagrama de pines de un display de 7 segmentos.
Ahora, una vez conocido el funcionamiento de los componentes individuales, a continuacin muestro el diagrama total del reloj, en donde veremos como estos integrados interactuan entre s para poder obtener nuestro sencillo reloj digital. Las resistencias que van a los displays son de 330 (Naranja, Naranja, Marrn) y las que van a los transistores son de 1K (Marrn, Negro, Rojo). Y claro, las resistencias que van a los pulsadores son de 10K (Marrn, Negro, Naranja).
Antes que nada tenemos que conectar los componentes bsicos para el funcionamiento del microcontrolador pic, que son las conexiones a tierra y 5 voltios, el reloj de 4MHz y los capacitores.
Luego podemos armar el siguiente diagrama esquemtico para tener en funcionamiento a nuestro sencillo Reloj Digital.
Archivos adjuntos del proyecto:
El cdigo est escritor en ensamblador. Pueden usar el mplab para recompilarlo y usarlo de acuerdo a sus necesidades. view plainprint? 1. __CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC 2. LIST P=16F84A 3. INCLUDE <P16F84A.INC> 4. 5. M_UNI equ H'1D' ; Registro para las unidades de los minutos. 6. M_DEC equ H'1C' ; Registro para las decenas de los minutos. 7. 8. H_UNI equ H'1F' ; Registro para las unidades de las horas. 9. H_DEC equ H'1E' ; Registro para las decenas de las horas. 10. 11. S_UNI equ H'20' ; Registro para las unidades de los segundos. 12. S_DEC equ H'21' ; Registro para las decenas de los segundos. 13. 14. BARR equ H'1B' ; Registro para almacenar el nmero de barridos. 15. PAUSE equ H'1A' ; Registro para almacenar el tiempo de barrido. 16. 17. ;Algunas definiciones de registros y pines 18. ;----------------------------------------- 19. #DEFINE REINICIO PORTA,0 ; Pulsador conectado a RA0. 20. #DEFINE MINUTO PORTA,1 ; Pulsador conectado a RA1. 21. #DEFINE HORA PORTA,2 ; Pulsador conectado a RA2. 22. #DEFINE DISPLAY PORTB ; El display est conectado al Puerto B. 23. 24. ORG 0 25. 26. Inicio 27. bsf STATUS,RP0 ; Acceso al Banco 1. 28. clrf DISPLAY ; Lnea del LED configurada como salida. 29. movlw b'00011111' ; Las 5 lneas del Puerto A se configuran como entrada. 30. movwf PORTA 31. bcf STATUS,RP0 ; Acceso al Banco 0. 32. ;Inicializacin de Registros 33. ;--------------------------- 34. clrf S_UNI 35. clrf S_DEC 36. clrf M_UNI 37. clrf M_DEC 38. clrf H_UNI 39. clrf H_DEC 40. clrf BARR 41. ;--------------------------- 42. 43. Principal 44. clrf BARR ; Limpiamos el registro de barridos 45. ;Para el botn de reinicio no importa los rebotes 46. ;------------------------------------------------ 47. VerificarPulsadorReset 48. btfss REINICIO ; Pulsador reposo?, Pulsador=1? 49. call InicializarRegistros 50. ;------------------------------------------------------------------------------ 51. 52. ;Para el botn de incremento de minutos si importan los rebotes 53. ;-------------------------------------------------------------- 54. VerificarPulsadorMinutos 55. btfsc MINUTO ; Pulsador presionado?, (Pulsador)=0? 56. goto VerificarPulsadorHoras ; No vuelve a leerlo 57. call Temporizador ; Espera a que se estabilicen los niveles de tensin. 58. btfsc MINUTO ; Comprueba si es un rebote. 59. goto VerificarPulsadorHoras ; Era un rebote y sale. 60. goto SoloMinutosEnUno ; Salta a la subrutina para incrementar los minutos en 1 61. ;------------------------------------------------------------------------------ 62. 63. ;Para el botn de incremento de horas tambin importan los rebotes 64. ;----------------------------------------------------------------- 65. VerificarPulsadorHoras 66. ;------------------------------------------------------------------------------ 67. btfsc HORA ; Pulsador presionado?, (Pulsador)=0? 68. goto SoloSegundosEnUno ; No vuelve a leerlo 69. call Temporizador ; Espera a que se estabilicen los niveles de tensin. 70. btfsc HORA ; Comprueba si es un rebote. 71. goto SoloSegundosEnUno ; Era un rebote y sale fuera. 72. call SoloHorasEnUno 73. ;------------------------------------------------------------------------------ 74. 75. SoloSegundosEnUno 76. call IncrementarSegundosEnUno 77. 78. Mostrar 79. call ValidarTiempo 80. call Barrido 81. ;------------------------------------------------------------------------------ 82. 83. Fin 84. goto Principal 85. ;------------------------------------------------------------------------------ 86. 87. SoloMinutosEnUno 88. call IncrementarMinutosEnUno 89. goto Mostrar 90. 91. SoloHorasEnUno 92. call IncrementarHorasEnUno 93. goto Mostrar 94. 95. ;************************************* 96. ; Subrutina de Incremento de Registros 97. ;************************************* 98. 99. ;------------------------------------------------------------------------------ 100. IncrementarSegundosEnUno 101. incf S_UNI,f ; Incrementa el valor de S_UNI 102. movfw S_UNI ; Carga W con el valor del regustro S_UNI 103. sublw D'10' ; Resta 10 para verificar si S_UNI=10? 104. btfsc STATUS, Z ; Verifica si el resultado fu cero 105. call IncrementarSegundosEnDiez ; Si es cero, entonces acarreamos uno 106. return 107. ;------------------------------------------------------------------------------ 108. 109. IncrementarSegundosEnDiez 110. clrf S_UNI ; El acarreo implica limpiar el registro anterior 111. incf S_DEC,f ; Incrementa el valor de S_DEC 112. movfw S_DEC ; Carga W con el valor del regustro S_DEC 113. sublw D'6' ; Resta 6 para verificar si S_UNI=6? 114. btfsc STATUS, Z ; Verifica si el resultado fu cero 115. call IncrementarMinutosEnUno ; Si es cero, entonces acarreamos uno 116. return 117. ;------------------------------------------------------------------------------ 118. 119. IncrementarMinutosEnUno 120. clrf S_DEC ; El acarreo implica limpiar el registro anterior 121. incf M_UNI,f ; Incrementa el valor de M_UNI 122. movfw M_UNI ; Carga W con el valor del regustro M_UNI 123. sublw D'10' ; Resta 10 para verificar si S_UNI=10? 124. btfsc STATUS, Z ; Verifica si el resultado fu cero 125. call IncrementarMinutosEnDiez ; Si es cero, entonces acarreamos uno 126. return 127. ;------------------------------------------------------------------------------ 128. 129. IncrementarMinutosEnDiez 130. clrf M_UNI ; El acarreo implica limpiar el registro anterior 131. incf M_DEC,f ; Incrementa el valor de M_DEC 132. movfw M_DEC ; Carga W con el valor del regustro M_DEC 133. sublw D'6' ; Resta 6 para verificar si S_UNI=6? 134. btfsc STATUS, Z ; Verifica si el resultado fu cero 135. call IncrementarHorasEnUno ; Si es cero, entonces acarreamos uno 136. return 137. ;------------------------------------------------------------------------------ 138. 139. IncrementarHorasEnUno 140. clrf M_DEC ; El acarreo implica limpiar el registro anterior 141. incf H_UNI,f ; Incrementa el valor de H_UNI 142. movfw H_UNI ; Carga W con el valor del regustro H_UNI 143. sublw D'10' ; Resta 6 para verificar si S_UNI=10? 144. btfsc STATUS, Z ; Verifica si el resultado fu cero 145. call IncrementarHorasEnDiez ; Si es cero, entonces acarreamos uno 146. return 147. ;------------------------------------------------------------------------------ 148. 149. IncrementarHorasEnDiez 150. clrf H_UNI ; El acarreo implica limpiar el registro anterior 151. incf H_DEC,f ; Incrementa el valor de H_DEC 152. movfw H_DEC ; Carga W con el valor del regustro H_DEC 153. sublw D'10' ; Resta 6 para verificar si S_UNI=10? 154. btfsc STATUS, Z ; Verifica si el resultado fu cero 155. clrf H_DEC ; Si es cero, entonces acarreamos uno 156. return 157. ;------------------------------------------------------------------------------ 158. 159. ;********************************* 160. ; Subrutina de Barrido de Displays 161. ;********************************* 162. 163. ;------------------------------------------------------------------------------ 164. 165. Barrido 166. btfss REINICIO ; Pulsador reposo?, Pulsador=1? 167. call InicializarRegistros 168. incf BARR, f ; Incrementa en 1 el registro de barridos 169. ;Unidades de segundos 170. ;-------------------- 171. movlw b'00001111' ; Activamos el primer display 172. movwf DISPLAY ; Movemos el dato al puerto B 173. movf S_UNI,0 ; Mueve M_UNI al registro W 174. iorlw b'00000000' ; Aplicamos la mscara 175. movwf DISPLAY ; Mostramos en el puerto B 176. call Temporizador ; Pausa para establecer niveles de tensin correctamente 177. movlw B'00001111' ; Cargamos el valor adecuado a W para limpiar los registros 178. movwf DISPLAY ; Limpiamos el display para evitar que los dgitos se repitan 179. ;------------------------------------------------------------------------------ 180. ;Decenas de segundos 181. movlw b'00011111' ; Activamos el segundo display 182. movwf DISPLAY ; Movemos el dato al puerto B 183. movf S_DEC,0 ; Mueve S_DEC al registro W 184. iorlw b'00010000' ; Aplicamos la mscara 185. movwf DISPLAY ; Mostramos en el puerto B 186. call Temporizador ; Pausa para establecer niveles de tensin correctamente 187. movlw B'00011111' ; Cargamos el valor adecuado a W para limpiar los registros 188. movwf DISPLAY ; Limpiamos el display para evitar que los dgitos se repitan 189. ;------------------------------------------------------------------------------ 190. ;Unidades de minutos 191. movlw b'00101111' ; Activamos el tercer display 192. movwf DISPLAY ; Movemos el dato al puerto B 193. movf M_UNI,0 ; Mueve M_UNI al registro W 194. iorlw b'00100000' ; Aplicamos la mscara 195. movwf DISPLAY ; Mostramos en el puerto B 196. call Temporizador ; Pausa para establecer niveles de tensin correctamente 197. movlw B'00101111' ; Cargamos el valor adecuado a W para limpiar los registros 198. movwf DISPLAY ; Limpiamos el display para evitar que los dgitos se repitan 199. ;------------------------------------------------------------------------------ 200. ;Decenas de minutos 201. movlw b'00111111' ; Activamos el cuarto display 202. movwf DISPLAY ; Movemos el dato al puerto B 203. movf M_DEC,0 ; Mueve M_UNI al registro W 204. iorlw b'00110000' ; Aplicamos la mscara 205. movwf DISPLAY ; Mostramos en el puerto B 206. call Temporizador ; Pausa para establecer niveles de tensin correctamente 207. movlw B'00111111' ; Cargamos el valor adecuado a W para limpiar los registros 208. movwf DISPLAY ; Limpiamos el display para evitar que los dgitos se repitan 209. ;------------------------------------------------------------------------------ 210. ;Unidades de horas 211. movlw b'01001111' ; Activamos el quinto display 212. movwf DISPLAY ; Movemos el dato al puerto B 213. movf H_UNI,0 ; Mueve M_UNI al registro W 214. iorlw b'01000000' ; Aplicamos la mscara 215. movwf DISPLAY ; Mostramos en el puerto B 216. call Temporizador ; Pausa para establecer niveles de tensin correctamente 217. movlw B'01001111' ; Cargamos el valor adecuado a W para limpiar los registros 218. movwf DISPLAY ; Limpiamos el display para evitar que los dgitos se repitan 219. ;------------------------------------------------------------------------------ 220. ;Decenas de horas 221. movlw b'01011111' ; Activamos el sexto display 222. movwf DISPLAY ; Movemos el dato al puerto B 223. movf H_DEC,0 ; Mueve M_UNI al registro W 224. iorlw b'01010000' ; Aplicamos la mscara 225. movwf DISPLAY ; Mostramos en el puerto B 226. call Temporizador ; Pausa para establecer niveles de tensin correctamente 227. movlw B'01011111' ; Cargamos el valor adecuado a W para limpiar los registros 228. movwf DISPLAY ; Limpiamos el display para evitar que los dgitos se repitan 229. ;------------------------------------------------------------------------------ 230. ;Verificar barrido 231. movfw BARR ; carga W con el nmero de barridos 232. sublw D'50' ; Resta 50 para comparar si es igual a 50 233. btfsc STATUS, Z ; Verifica si el resultado fu 0, o sea si BARR=50? 234. return ; Se complet el nmero de barridos 235. goto Barrido 236. ;------------------------------------------------------------------------------ 237. 238. ValidarTiempo 239. movfw H_UNI ; Carga el registro W con el valor del registro H_UNI 240. sublw D'4' ; Resta 4 para verificar si es que el valor de W=4? 241. btfsc STATUS, Z ; Verifica si el resultado fu cero 242. goto ValidarHora ; Ahora llamamos al subrutina para verificar el siguiente dgito d e la hora 243. return 244. ;------------------------------------------------------------------------------ 245. 246. ValidarHora 247. movfw H_DEC ; Carga el registro W con el valor del registro H_DEC 248. sublw D'2' ; Resta 2 para verificar si es que el valor de W=2? 249. btfsc STATUS, Z ; Verifica si el resultado fu cero 250. goto InicializarRegistros ; Al llamar a esta subrutina quiere decir que la hora=24, lo cul implica un reinicio 251. return 252. ;------------------------------------------------------------------------------ 253. 254. InicializarRegistros 255. clrf S_UNI 256. clrf S_DEC 257. clrf M_UNI 258. clrf M_DEC 259. clrf H_UNI 260. clrf H_DEC 261. return 262. ;------------------------------------------------------------------------------ 263. 264. Temporizador 265. movlw D'255' ; w = 50 decimal 266. movwf PAUSE ; K = w 267. 268. Kloop 269. decfsz PAUSE,f ; K = K - 1 , salta a la siguiente instruccin si es cero. 270. goto Kloop 271. return 272. ;------------------------------------------------------------------------------ 273. 274. END ; Fin del programa.