====== NMK32203 - Microcontroller ======
//**Note20241017** This page is being updated - work in progress...//
This course is //Microcontroller//, offered by the Faculty of Electronics Engineering & Technology.
===== Announcements =====
[20241017] Updating this for 202425s1 Academic Session.
===== Lecture Slides =====
* Lecture 1 - {{:archive:nmk322:lecture01_overview.pdf|Overview}}
* Lecture 2 - {{:archive:nmk322:lecture02_arch8051.pdf|Architecture}}
* Lecture 3 - {{:archive:nmk322:lecture03_c8051.pdf|C for 8051}}
* Lecture 4 - {{:archive:nmk322:lecture04_gpio.pdf|8051 I/O}}
* Lecture 5 - {{:archive:nmk322:lecture05_timer.pdf|8051 Timer}}
* Lecture 6 - {{:archive:nmk322:lecture06_serial.pdf|8051 Serial Interface}}
* Lecture 7 - {{:archive:nmk322:lecture07_interrupt.pdf|8051 Interrupt}}
* Lecture 8 - {{:archive:nmk322:lecture08_system.pdf|8051 System Management}}
===== Library Codes =====
Introduction to using 'library' code. Single header include file(s) meant for single source compilation. These are meant to be compiled using Keil 8051 compiler.
I recommend to use my include file (mcu51.h) rather than the regular (reg51.h) because it would be easier for you to use my example codes and library. I wrote and tested them using my own syntax that can be used on both Keil and SDCC compilers. Simply extract this {{:archive:nmk322:my1code51inc-20241210.zip|zip file}} and setup the include path. Ask me during lab session if you do not know how to do that.
==== Library: Serial (UART) ====
#ifndef __MY1UART_H__
#define __MY1UART_H__
/* note: this is NOT compatible with keil's printf */
void uart_init(void) {
SCON = 0x50;
TMOD &= 0x0F;
TMOD |= 0x20;
TH1 = 253;
TR1 = 1;
}
void uart_send(unsigned char sdat) {
SBUF = sdat;
while (TI==0);
TI = 0;
}
unsigned char uart_read(void) {
unsigned char rdat;
while (RI==0);
rdat = SBUF;
RI = 0;
return rdat;
}
void uart_puts(char* text) {
while (*text) {
uart_send(*text);
text++;
}
}
#endif /* __MY1UART_H__ */
==== Library: Text LCD ====
#ifndef __MY1TLCD_H__
#define __MY1TLCD_H__
#define LCD_DATA P2
sbit LCD_RS = P0^7;
sbit LCD_RW = P0^6;
sbit LCD_EN = P0^5;
void tlcd_delay(unsigned char step) {
unsigned int loop;
do {
loop = 1000; while (--loop);
} while (--step);
}
void tlcd_write(unsigned char cdat) {
LCD_RS = 1;
LCD_RW = 0;
LCD_DATA = cdat;
LCD_EN = 1;
LCD_EN = 0;
tlcd_delay(1);
}
void tlcd_cmd(unsigned char ccmd) {
LCD_RS = 0;
LCD_RW = 0;
LCD_DATA = ccmd;
LCD_EN = 1;
LCD_EN = 0;
tlcd_delay(2);
}
void tlcd_init(void) {
tlcd_cmd(0x38); /* 8 bit mode, 1/16 duty, 5x8 font */
tlcd_cmd(0x38);
tlcd_cmd(0x38);
tlcd_cmd(0x06); /* display off */
tlcd_cmd(0x0c); /* display on, blink cursor on */
tlcd_cmd(0x01); /* clear display */
}
void tlcd_puts(char* text) {
while (*text) {
tlcd_write(*text);
text++;
}
}
#endif /* __MY1TLCD_H__ */
==== Library: Timer ====
#ifndef __MY1TIMER_H__
#define __MY1TIMER_H__
// useful macro!
#define timer0_init() { TMOD &= 0xF0; TMOD |= 0x01; }
#define timer0_prep(hi,lo) { TH0 = hi; TL0 = lo; }
#define timer0_stop() { TR0 = 0; TF0 = 0; }
#define timer0_exec() { TR0 = 1; }
#define timer0_flag() { timer0_exec(); while (!TF0); }
#define timer0_wait(hi,lo) { timer0_prep(hi,lo); timer0_flag(); timer0_stop(); }
#define timer0_null() { TH0 = 0; TL0 = 0; }
#define timer0_read() ((unsigned int)TH0<<8)|TL0
void timer0_delayms(unsigned int step) {
do {
timer0_wait(0xfc,0x66); // 1 ms delay
} while (--step);
}
#endif /* __MY1TIMER_H__ */
==== Library: Utilities (str-int conversions) ====
#ifndef __MY1UTILS_H__
#define __MY1UTILS_H__
unsigned char uint8_2cstr(char* cstr, unsigned char that) {
unsigned char size, temp;
size = 0;
temp = that/100;
if (temp) {
that %= 100;
cstr[size++] = temp + 0x30;
}
temp = that/10;
if (temp) {
that %= 10;
cstr[size++] = temp + 0x30;
} else if (size)
cstr[size++] = 0x30;
cstr[size++] = that + 0x30;
cstr[size] = 0x0;
return size;
}
unsigned char int8_2cstr(char* cstr, signed char that) {
if (that<0) {
that = -that;
*cstr = '-';
cstr++;
}
return uint8_2cstr(cstr,(unsigned char)that);
}
unsigned char uint16_2cstr(char* cstr, unsigned int that) {
unsigned char size, temp;
unsigned int idiv;
size = 0; idiv = 10000;
while (idiv>=10) {
temp = (unsigned char)(that/idiv);
if (temp) {
that %= idiv;
cstr[size++] = temp + 0x30;
} else if (size)
cstr[size++] = 0x30;
idiv /= 10;
}
cstr[size++] = that + 0x30;
cstr[size] = 0x0;
return size;
}
unsigned char int16_2cstr(char* cstr, int that) {
if (that<0) {
that = -that;
*cstr = '-';
cstr++;
}
return uint16_2cstr(cstr,(unsigned int)that);
}
unsigned char cstr_2uint8(char* pstr, unsigned char* pval) {
unsigned char loop;
*pval = 0; loop = 0;
while (pstr[loop]) {
if (pstr[loop]<0x30||pstr[loop]>0x39) {
loop = 0;
break;
}
*pval = (*pval*10) + (pstr[loop]-0x30);
loop++;
}
return loop;
}
unsigned char cstr_2uint16(char* pstr, unsigned int* pval) {
unsigned char loop;
*pval = 0; loop = 0;
while (pstr[loop]) {
if (pstr[loop]<0x30||pstr[loop]>0x39) {
loop = 0;
break;
}
*pval = (*pval*10) + (pstr[loop]-0x30);
loop++;
}
return loop;
}
unsigned char cstr_2int16(char* pstr, int* pval) {
unsigned char loop, skip;
skip = (pstr[0]=='-') ? 1 : 0;
loop = cstr_2uint16(&pstr[skip],(unsigned int*)pval);
if (skip) *pval = -(*pval);
return loop;
}
#endif /** __MY1UTILS_H__ */
==== Library: Keypad ====
#ifndef __MY1KPAD_H__
#define __MY1KPAD_H__
/* 4x4 keypad interface {R0,R1,R2,R3,C0,C1,C2,C3} */
/* 4x3 keypad interface {C1,R0,C0,R3,C2,R2,R1} */
/** DefaultPins: C0-C3 => P1.4-P1.7, R0-R3 => P1.0-P1.3 */
#ifndef KEY_DATA
#define KEY_DATA P1
#endif
#ifndef _ROWS_AT_UPPER_
#define ROWS_FLAG 0x01
#define COLS_FLAG 0x10
#else
#define ROWS_FLAG 0x10
#define COLS_FLAG 0x01
#endif
/** no-key indicator for keypad */
#define KEY_NOT_CODE 0x10
unsigned char key_scan(void) {
/** scan for key press */
unsigned char irow, icol, mask, test;
mask = ROWS_FLAG;
for (irow=0;irow<4;irow++) {
KEY_DATA = ~mask; test = COLS_FLAG;
for (icol=0;icol<4;icol++) {
if ((KEY_DATA&test)==0) {
while ((KEY_DATA&test)==0);
if (icol==3) return irow+0x0A;
if (irow==0) return icol+1;
if (irow==1) return icol+4;
if (irow==2) return icol+7;
if (icol==1) return 0;
return (icol>>1)+0x0e;
}
test <<= 1;
}
mask <<= 1;
}
return KEY_NOT_CODE;
}
unsigned char key_wait(void) {
/** wait for key press */
unsigned char scan;
while ((scan=key_scan())==KEY_NOT_CODE);
return scan;
}