Thiết kế hệ thống phần mềm cho c at90s8535

Các mạch số trong và ngoài C AT90S8535 có thể tạo ra EMI làm ảnh hưởng đến sự chính xác của việc lấy mẫu tính hiệu tương tự. Nếu độ chính xác của sự chuyển đổi bị lỗi thì có thể giảm nhiễu bằng việc áp dụng các kỹ thuật sau: 1. Phần tương tự của C AT90S8535 và tất cả các thành phần tương tự trong ứng dụng nên có một chân nối đất tương tự riêng trên PCB. Chân nối đất này được nối tới chân nối đất số qua một điểm đơn trên PCB. 2. Giữ cho đường đi của tín hiệu tương tự càng ngắn càng tốt. Đảm bảo các đường đi của tín hiệu tương tự hướng tới chân nối đất tránh sự chuyển đổi sang các đường số tốc độ cao. 3. Chân AVCC trên C AT90S8535 nên được nối tới chân VCC qua một mạch LC như trong hình 2.30. 4. Sử dụng chức năng khử nhiễu của ADC để giảm nhiễu sinh ra từ MCU. 5. Nếu một số chân cổng A được sử dụng như các đầu ra số thì các chân này không được chọn khi một quá trình chuyển đổi đang diễn ra.

doc140 trang | Chia sẻ: oanh_nt | Lượt xem: 1614 | Lượt tải: 0download
Bạn đang xem trước 20 trang tài liệu Thiết kế hệ thống phần mềm cho c at90s8535, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
diện LCD), • (dịch chuyển chuỗi được lựa chọn trên giao diện LCD sang trái một ký tự), – (dịch chuyển chuỗi được lựa chọn trên giao diện LCD sang phải một ký tự), —/˜ (lựa chọn chuỗi hiển thị trong TxBuff hay RxBuff), Clear (xoá chuỗi được lựa chọn trên giao diện LCD và bộ đệm tương ứng). Nếu là phím thường, ngắt xác định thời gian lặp phím KEY_RATE bị cấm để chương trình điều kiển có thể xác định đúng số lần phím được ấn lại (do mỗi phím được mã hoá nhiều hơn 2 ký tự). Các thao tác tiếp theo được thực hiện bởi chương trình con DISPLAY_KEY, được goi từ chương trình điều khiển. Ngắt cho phép chuyển đổi A/D : Do mục đích sử dụng trong đồ án, nên chu kỳ chuyển đổi của bộ ADC trong mC cần một thời gian lâu hơn rất nhiều so với thời gian chuyển đổi thực tế mà bộ ADC có thể đạt được. Để có thể kéo dài chu kỳ chuyển đổi của bộ ADC, ngắt so sánh bằng của bộ Timer/Counter1 được sử dụng. Ngắt này được gọi với chu kỳ 10ms và chức năng của nó là cho phép bộ ADC lấy mẫu thực hiện chuyển đổi A/D. Ngắt xác định thời gian lặp phím : Do mỗi một phím thường trên bàn phím được mã hoá nhiều hơn 2 ký tự. Vì vậy, cần phải xác định ký tự nào thực sự được lựa chọn trong số các ký tự mã hoá bởi phím được ấn. Để làm được điều này, ngắt tràn của bộ Timer/Counter1 được sử dụng với chu kỳ 200ms. Khi một phím thường được ấn, ngắt này được reset và nếu trước khi cờ ngắt này được dựng mà phím được ấn lại thì ký tự tiếp theo được phím mã hoá sẽ được lựa trọn. Ngắt nhận dữ liệu : Khi mC AT90S8535 nhận được một byte dữ liệu từ PC, ngắt kết thúc nhận dữ liệu của bộ UART được gọi. Ngắt này có nhiệm vụ kiểm tra dữ liệu nhậ được là mã lệnh hay là ký tự hiển thị. Nếu là mã lệnh, cờ báo nhận lệnh từ PC được dựng và mã lệnh được lưu lại trong thanh ghi Implement. Sau đó lệnh tương ứng sẽ được thực hiện từ chương trình điều khiển thông qua lời gọi đến chương trình con EXCUTER_FROM_PC. Nếu nhận ký tự hiển thị, ký tự này sẽ được lưu vào bộ đêm RxBuff cho đến khi nhận được mã phím Enter cờ báo cần hiển thị chuỗi ký tự nhận được sẽ được dựng và dữ liệu sẽ được hiển thị trên giao diện LCD. Ngắt kết thúc chuyển đổi A/D : Ngắt này được gọi sau khi một thao tác chuyển đổi A/D hoàn thành. Ngắt này có nhiệm vụ chuyển kết quả chuyển đổi từ số hệ 2 sang số hệ 10, kết quả này sẽ được gửi sang PC đồng thời dựng cờ báo có kết quả chuyển đổi A/D. Thao tác tiếp theo được thực hiện trong chương trình con DISPLAY_TEMPR_TO_LCD được gọi từ chương trình điều khiển khi cờ trên được nhận ra. Ngoài các ngắt kể trên, chương trình còn có một số chương trình con có các chức năng khác nhau trợ giúp cho chương trình điều khiển hoạt động, bao gồm : Các chương trình con điều khiển LCD controller : LCD_BUSY (kiểm tra LCD controller đang thực hiện thao tác trong?), LCD_INSTR (ghi lệnh tới LCD controller) và LCD _DATA (ghi dữ liệu tới LCD controller). Các chương trình con tính toán và hiển thị kết quả thu được từ ADC : MULL_RESULT_CONVER, DIVIDE_TO_GET_TEMPR (thực hiện nhân chia 16 bit để thu được kết quả ADC ở số hệ 10), DISPLAY_TEMPR_TO_LCD (hiển thị kết quả của ADC ra giao diện LCD dưới dạng 0C hay 0K tuỳ thuộc vào điều kiện được xác định trong chương trình). Các chương trình điều khiển của các phím chức năng : SHIFT_LEFT, SHIFT_RIGHT, SEND_TxBUFF_TO_PC, CLEAR_Tx_OR_Rx, BACK_SPACE, SELECT_TxRx. Các chương trình điều khiển đối với phím thường : GET_ASCII_CODE (xác định mã ASCII của phím được ấn), FIND_ASCII_CODE (tìm mã ASCII tươngứng với số lần ấn của phím), DISPLAY_KEY (hiển thị phím được ấn và lưu vào bộ đếm TxBuff để chuyền sang PC). Các chương trình điều khiển hiển thị dữ liệu ra giao diện LCD : SHOW_PREFACEA, SHOW_PREFACEB (hiển thị lời giới thiệu), DISPLAY_INTERFACE (hiển thị giao diện làm việc của LCD), SHOW_STRING (hiển thị một chuỗi ký tự ra giao diện LCD) vv... 4.2. Lưu đồ thuật toán của các chức năng chính. 4.2.1. Chức năng giao tiếp với LCD controller. Để mC có thể giao tiếp được với LCD controller, ta cần thực hiện khởi tạo LCD controller ngay sau khi nguồn được bật. Do mục đích của đồ án, ta sử dụng cơ chế khởi tạo LCD controller ở chế độ giao tiếp 4 bit bus. 3 chương trình con được sử dụng để giao tiếp với LCD controller là LCD_BUSY, LCD_INSTR và LCD_DATA. Lệnh được đặt trong thanh ghi Instr và dữ liệu trong thanh ghi Data. Hình 4.3 : Lưu đồ chương trình kiểm tra LCD busy Bắt đầu Cho phép đọc thanh ghi lệnh của LCD controller (RS = 0, RW = 1) Đọc 4 bit MSB của thanh ghi lệnh Đọc 4 bit LSB của thanh ghi lệnh Kết thúc BF = 1? N Y Hình 4.4 : Lưu đồ chương trình ghi lệnh và dữ liệu tới LCD controller Bắt đầu Cho phép ghi thanh ghi lệnh của LCD controller (RS = 0, RW = 0) Ghi 4 bit MSB của mã lệnh tới thanh ghi lệnh Kết thúc Lấy 4 bit thấp của mã lệnh Ghi 4 bit LSB của mã lệnh tới thanh ghi lệnh Bắt đầu Cho phép ghi thanh ghi dữ liệu của LCD controller (RS = 1, RW = 0) Ghi 4 bit MSB của byte dữ liệu tới thanh dữ liệu Kết thúc Lấy 4 bit thấp của byte dữ liệu Ghi 4 bit LSB của byte dữ liệu tới thanh dữ liệu 4.2.2. Chức năng điều khiển và hiển thị kết quả ADC. Khi bộ ADC thực hiện xong một chu kỳ chuyển đổi, kết quả chuyển đổi sẽ được lưu vào thanh ghi ADCL và ADCH, tiếp sau đó cờ ngắt kết thúc chuyển đổi A/D được dựng và chương trình con phục vụ ngắt tương ứng là END_CONVERT được gọi. Hình 4.6 : Lưu đồ chương trình con phục vụ ngắt END_CONVERT Bắt đầu Lưu lại trạng thái MCU Lấy kết quả chuyển đổi A/D Lưu lại các thanh ghi cần sử dụng Gửi ký hiệu truyền dữ liệu ( # ) sang PC Lấy phần nguyên của kết quả ADC đặt vào ResultADCH Thực hiện chương trình MULL_RESULT_CONVER với số nhân = 100 Thực hiện chuơng trinh DIVIDE_TO_GET_TEMPR với số chia = 255 Gửi phần nguyên của kết quả ADC sang PC Lấy phần thập phân của kết quả ADC đặt vào ResultADCL Thực hiện chương trình MULL_RESULT_CONVER với số nhân = 10 Thực hiện chuơng trinh DIVIDE_TO_GET_TEMPR với số chia = 255 Gửi phần thập phân của kết quả ADC sang PC Dựng cờ báo cần hiển thị kết quả ADC ra giao diện LCD Lấy lại giá trị các thanh ghi sử dụng Lấy lại trạng thái MCU Kết thúc Trong ngắt END_CONVERT có sử dụng hai module MULL_RESULT_CONVER và DIVIDE_TO_GET_TEMPR được sử dụng để chuyển kết quả ADC sang số thập phân. Trước khi thực hiện các module này cần phải xác định số nhân hoặc số chia trong thanh ghi Data. Chương trình MULL_RESULT_CONVER sẽ thực hiện nhân nội dung hai thanh ghi ResultADCL và Data, kết quả đặt trong thanh ghi ResultADCH và ResultADCL. Chương trình DIVIDE_TO_GET_TEMPR thực hiện chia kết quả từ chương trình MULL_RESULT_CONVER cho nội dung thanh ghi Data, phần nguyên của kết quả đặt trong thanh ghi ResultADCH, phần dư của kết quả đặt trong thanh ghi ResultADCL. Hình 4.7 : Lưu đồ chương trình MULL_RESULT_CONVER Bắt đầu Xoá cờ carry ( C = 0 ) Khởi tạo các thanh ghi tạm R11 = 0, R12 = ResultADCL Giảm số nhân đi một Data ‘ Data - 1 Kết thúc Data = 0? Y N ResultADCL ‘ ResultADCL + R12 ResultADCH ‘ ResultADCH + R11 + C Hình 4.8 : Lưu đồ chương trình DIVIDE_TO_GET_TEMPR Bắt đầu Xoá cờ carry ( C = 0 ) Khởi tạo các thanh ghi tạm R11 ‘ 0, R12 ‘ 0 ResultADCL ‘ ResultADCL - Data ResultADCH ‘ ResultADCH - R11 - C C ‘ 0 R12 ‘ R12+1 Kết thúc N Lấy phần nguyên của kết quả ResultADCH ‘ R12 ResultADCL < Data? N ResultADCH = 0? Y Y Ngoài hai module trên, để hiển thị kết quả chuyển đổi A/D tới giao diện LCD, cần sử dụng chương trình con DISPLAY_TEMPR_TO_LCD chương trình này được gọi từ chương trình điều khiển khi cờ báo có kết quả ADC cần được hiển thị. Dữ liệu đầu vào của chương trình này là nội dung hai thanh ghi chứa kết quả A/D dưới dạng số hệ 10 sau khi thực hiện ngắt END_CONVERT, trong đó phần nguyên chứa trong thanh ghi ResultADCH và phần thập chứa trong thanh ghi ResultADCL. Hình 4.9 : Lưu đồ chương trình con DISPLAY_TEMPR_TO_LCD Kết thúc Bắt đầu Lấy toạ độ đầu Instr ‘ $CB Lưu nội dung ResultADCL ResultADCL ‘ ResultADCH ResultADCL ‘ 0 N Show_CK = 1? Y Đổi giá trị nhiệt độ sang 0K ResultADCH:ResultADCL ‘ ResultADCH:ResultADCL + 273 Lấy số hàng trăm để hiển thị Gọi chương trình DIVIDE_TO_GET_TEMPR với Data = $64 Y ResultADCH = 0? N Lấy mã ASCII của số cần hiển thị Data ‘ ResultADCH Data ‘ Data + 30 Không hiển thị số hàng trăm Data ‘ $20 Hiện dữ liệu Lấy số hàng chục để hiển thị ResultADCH ‘ 0 Gọi chương trình DIVIDE_TO_GET_TEMPR với Data = $0A Y ResultADCH = 0? N Lấy mã ASCII của số cần hiển thị Data ‘ ResultADCH Data ‘ Data + $30 Hiện 0 ở hàng chục Data ‘ $30 Hiện dữ liệu Hiện số hàng đơn vị Data ‘ ResultADCL Data ‘ Data + $30 Hiện dữ liệu Hiện dấu chấm thập phân Data ‘ $2E Hiện dữ liệu Hiện số thập phân Lấy lại nội dung ResultADCL Data ‘ ResultADCL Data ‘ Data + $30 Hiện dữ liệu 4.2.3. Chức năng giao tiếp với KeyPad. Chức năng giao tiếp với bàn phím được bắt đầu bằng việc giải mã ma trận bàn phím để xác định phím nào trên bàn phím được ấn. Để mC nhận biết có phím ấn, một yêu ngắt ngoài được xác định bằng mức thấp trên chân INT0 (PD2) được phát sinh và ngắt bàn phím SCAN_CODE được thực hiện. Trước khi bắt thực hiện chương trình con phục vụ ngắt, cần đặt 0 trên các hàng và đặt 1 trên các cột. Hình 4.10 : Lưu đồ ngắt SCAN_CODE giải mã ma trận bàn phím Bắt đầu Lưu lại trạng thái MCU Keypress ‘ 0 Câm ngắt bàn phím Đợi 0.2ms cho cổng ổn định Col1 = 0? Y N Col2 = 0? Y N Col3 = 0? Y N Col4 = 0? Y N KeyPress ‘ 0 KeyPress ‘ 4 KeyPress ‘ 8 KeyPress ‘ 12 Đảo 4 bit của cổng B Đưa 0 ra các cột vào đưa 1 ra các hàng Đợi 0.2ms cho các cột ổn định Row1 = 0? Y N KeyPress ‘ KeyPress + 0 Row2 = 0? Y N KeyPress ‘ KeyPress + 1 Row3 = 0? Y N KeyPress ‘ KeyPress + 3 A B Kết thúc Row4 = 0? Y N KeyPress ‘ KeyPress + 4 A B KeyPress<10? N Y Dựng cờ báo phím điều khiển Dựng cờ báo có phím ấn Cấn ngắt KEY_RATE Lấy lại trạng thái MCU Do mỗi một phím thường trên bàn phím được mã hoá nhiều hơn một ký tự, vì vậy để xác định được chính xác ký tự nào được mã hoá của phím bị ấn được lựa chọn một thanh ghi OldKey được sử dụng. Nội dung của thanh ghi này chứa giá trị của phím được ấn và được dùng để so sánh với giá trị của phím được ấn trong thanh ghi KeyPress ở lần tiếp theo. Nếu hai thanh ghi này có giá trị bằng nhau thì tổng số lần ấn phím tăng lên 1 và ký tự tiếp theo được mã hoá bởi phím sẽ được chọn, ngược lại phím được coi là ấn lần đầu tiên. Nội dung thanh ghi OldKey sẽ được ghi nhớ trong một khoảng thời gian 200ms, nếu sau khoảng thời gian này mà phím không được ấn lại nội dung thanh ghi OldKey được xác lập lại trang thái không phím nào được ấn (OldKey = -1). Việc này được thực hiện bởi chương trình phục vụ ngắt KEY_RATE của ngắt tràn TC1. Hình 4.11 : Lưu đồ ngắt KEY_RATE Kết thúc Lưu trạng thái MCU Cấn ngắt KEY_RATE Lấy lại trạng thái MCU Bắt đầu OldKey ‘ -1 Tuỳ thuộc vào phím được ấn là phím điều khiển hay phím thường mà chương trình điều khiển sẽ thực hiện một trong hai chương trình con DISPLAY_KEY ứng với một phím thường và CONTROL_KEY ứng với một phím điều khiển. Hình 4.12 : Lưu đồ chương trình DISPLAY_KEY Kết thúc Gọi chương trình FIND_ASCII_CODE Hiện thông báo tràn bộ đệm TxBuff Bắt đầu LPtrTx = EndTxBuf+1? Y N Tăng con trỏ cuối bộ đệm TxBuff LPtrTx ‘ LPtrTx + 1 Hiện 15 ký tự cuối trong bộ đệm Gọi chương trình SHOW_CHAR_IN_TxBuff Xác định vị trí hiển thị tiếp theo Hiện ký tự tương ứng phím ấn Lưu ký tự vào bộ đệm TxBuff XL ‘ LPTrTx, X ‘ Data Giảm con trỏ cuối bộ đệm TxBuff LPtrTx ‘ LPtrTx - 1 Chương trình con FIND_ASCII_CODE có chức năng tìm mã ascii tương ứng với ký tự được lựa chọn và lưu kết quả vào thanh ghi Data với số lần phím được ấn lưu trong 4 bit cao của thanh ghi điều khiển CtrlReg. Hình 4.13 : Lưu đồ chương trình FIND_ASCII_CODE Bắt đầu Tăng tổng số lần ấn phím Xác định vị trí hiển thị và con trỏ LPtrTx KeyPress = OldKey? N Y A OldKey ‘ KeyPress Tổng số lần ấn phím = 0 Số lần ấn phím = 4 ? N Y B Data ‘ $38 Position ‘ $58 Data ‘ $37 Position ‘ $55 Temp ‘ 0 CtrlReg ‘ CtrlReg—$0F Data ‘ $39 Position ‘ $19 A B Tổng số lần ấn phím = 0 CtrlReg ‘ CtrlReg—$0F Lấy tổng số lần ấn phím Temp ‘ CtrlReg swap Temp Temp ‘ Temp—$0F Keypress<5? N C Y Keypress<3? N Y Keypress= 1? Y N Data ‘ $31 Position ‘ $43 Keypress= 2? Y Data ‘ $32 Position ‘ $46 N Data ‘ $30 Position ‘ $40 Keypress=4? N Y Data ‘ $33 Position ‘ $49 Data ‘ $34 Position ‘ $4C Lấy mã ASCII của ký tự tương ứng chương trình GET_ASCII_CODE Kết thúc C Keypress<7? Y N Keypress= 6? N Y Data ‘ $35 Position ‘ $4F Data ‘ $36 Position ‘ $52 Keypress= 8? Y N Temp= 3? N Y Temp ‘ 0 CtrlReg ‘ CtrlReg—$0F Keypress= 9? Y N Temp= 2? N Y Tổng số lần ấn phím = 0 CtrlReg ‘ CtrlReg—$0F Chương trình con GET_ASCII_CODE có chức năng lấy mã ascii và lưu vào trong thanh ghi Data. Đầu vào của chương trình là thanh ghi Data chứa mã ascii của chữ số và thanh ghi Position chứa mã ascii của ký tự đứng ngay trước ký tự đầu tiên được mã hoá bởi phím. Ví dụ, phím số 1 mã hoá các ký tự 1, D,E và F, khi đó nếu phím số 1 được ấn thì Data chứa giá trị $30 (mã ascii của số 1) còn Position chứa giá trị $43 (mã ascii của ký tự đứng trước chữ D). Tổng số lần ấn phím được đặt trong thanh ghi Temp. Hình 4.14 : Lưu đồ chương trình GET_ASCII_CODE Bắt đầu Position ‘ Position + Temp Data ‘ Postion Temp = 0? Y N Kết thúc Trước khi hiển thị ký tự của phím được ấn ra màn hình LCD, chương trình DISPLAY_KEY, gọi chương trình con SHOW_CHAR_IN_TxBuff để hiện thị lại 15 ký tự cuối cùng được lưu trong bộ đệm TxBuff, nếu tổng số ký tự đang có trong bộ đệm TxBuff lớn hơn 15 ký tự. Ngoài chương trình DISPLAY_KEY được thực hiện khi một phím thường được ấn. Một chương trình khác là chương CONTROL_KEY sẽ được chương trình điều khiển thực hiện mỗi khi một phím chức năng được ấn. Trên bàn phím có tất cả 6 phím chức năng như trình bầy ở các phần trước. Tuỳ thuộc vào việc giải mã bàn phím các chương trình con tương ứng với phím chức năng bị ấn sẽ được thực hiện. Hình 4.15 : Lưu đồ chương trình CONTROL_KEY Kết thúc Bắt đầu Gọi chương trình BACK_SPACE KeyPress <13? N Y Xoá cờ báo phím điều khiển Y N Gọi chương trình SHIFT_LEFT N Y Gọi chương trình SEND_TxBUFF_TO_PC KeyPress =11? KeyPress =10? Gọi chương trình SELECT_TxRx Y N Gọi chương trình SHIFT_RIGHT N Y Gọi chương trình CLEAR_Tx_OR_Rx KeyPress =14? KeyPress =15? 4.2.4. Chức năng truyền nhận dữ liệu nối tiếp với PC. Khi PC thực hiện truyền dữ liệu cho mC, thì mỗi khi mC hoàn thành việc nhận một byte dữ liệu từ cổng nối tiếp, cờ ngắt kết thúc nhận của bộ UART trên mC AT90S8535 được dựng. Chương trình con phục vụ ngắt tương ứng là Rx_COMPELET được thực hiện. Chương trình này có nhiệm vụ phân biệt dạng dữ liệu nhận được từ PC là mã lệnh hay chuỗi ký tự hiển thị để báo cho chương trình điều khiển thực hiện những tác vụ tương ứng. Hình 4.16 : Lưu đồ ngắt Rx_COMPELET Bắt đầu Lưu lại trạng thái MCU Lưu thanh ghi cần sử dụng Kết thúc Đọc dữ liệu nhận được Data ‘ URD Mã lệnh? Y N Ký tự #? Y N CR? Y N Xác định địa chỉ cần lưu ký tự vừa nhận trong RxBuff Ghi ký tự vừa nhận vào bộ đệm RxBuff Xác định con trỏ hiển thị của chuỗi ký tự Lấy lại giá trị các thanh ghi Lấy lại trạng thái MCU Lấy mã lệnh Implement ‘ Data Xoá cờ báo nhận mã lệnh Dựng cờ báo nhận mã lệnh Dựng cờ báo cần hiển thị dữ liệu nhận được Khi mC nhận được một lệnh từ PC gửi tới, thanh ghi chứa mã lệnh Implement sẽ chứa giá trị mã hoá của lệnh. Khi mC nhận được một lệnh từ CPU, chương trình con EXCUTER_FROM_PC sẽ được gọi để thực hiện lệnh. Trong đồ án này, chương trình trên PC chỉ có thể truyền hai lệnh đơn giản cho mC thực hiện là hiển thị giá trị nhiệt độ theo 0C hay 0K. Hình 4.17 : Lưu đồ chương trình con EXCUTER_FROM_PC Bắt đầu Xác lập lại nội dung thanh ghi mã lệnh Implement ‘ -1 Hiển thị 0C? Y N Kết thúc Xoá cờ cho phép hiển thị theo độ K Dựng cờ cho phép hiển ký hiệu dạng nhiệt độ hiển thị Dựng cờ cho phép hiển thị theo độ K Không chỉ có khả năng nhận dữ liệu từ PC, mà mC AT90S8535 cũng có thể gửi một chuỗi dữ liệu trong bộ đệm TxBuff sang PC tại bất kỳ thời điểm nào mỗi khi phím Send trên bàn phím được ấn. Hình 4.18 : Lưu đồ chương trình SEND_TxBUFF_TO_PC Bắt đầu SelectRx? Y N Kết thúc TxBuff = 0? Y N Hiện thông báo truyền dữ liệu Lấy địa chỉ đầu của bộ đệm XL ‘ LOW(TxBuff) Truyền dữ liệu sang PC Chương 5 Thiết kế hệ thống phần mềm trên PC 5.1. Mục đích của phần mềm trên PC. Để hệ thống có thể giao tiếp được với máy tính, ta cần phải thiết kế một phần mềm trên máy tính để nó có thể giao tiếp được với mC. Điều này có nghĩa là ta phải thiết lập một hệ thống trao đổi dữ liệu giữ máy tính và mC, nhằm mục đích tạo ra một sự kết hợp giữa máy tính và mC để tạo nên một hệ thống hoàn chỉnh cho dù chúng ở cách xa nhau. Mặt khác, so với mC thì PC có nhiều khả năng xử lý dữ liệu với độ phức tạp cao, điều này làm cho hệ thống hoạt động một cách thực sự có hiệu quả. Toàn bộ chương trình phần mềm viết cho PC được thực hiện trên ngôn ngữ Visual C++ 6.0. Phương pháp trao đổi dữ liệu giữa PC và mC được thực hiện theo phương pháp truyền nối tiếp theo chuẩn RS232 như đã trình bầy ở các chương trước. Sơ đồ tổng thể của chương trình viết trên PC như trên hình 5.1. Hình 5.1 : Sơ đồ khối chương trình viết trên PC Chương trình Truyền thông tin sang mC qua cổng RS232 Nhận dữ liệu từ giao diện nối tiếp RS232 Xử lý dữ liệu nhận được Hiện thông tin nhận được từ mC Hiện dữ liệu nhận được từ mC Lưu trữ dữ liệu nhận được Sau khi chương trình được khởi động, nó sẽ do tìm port nối tiếp và thiết lập kết nối với mC. Nếu kết nối không được thực hiện, thì thao tác truyền nhận dữ liệu giữa PC và mC sẽ không được thực hiện. Trong trường hợp này, chương trình chỉ thực hiện các thao tác với các thông tin đã được lưu lại trên PC. Khi kết nối thành công chương trình sẽ liên tục nhận dữ liệu được gửi từ mC, khi đó chương trình sẽ thực hiện các xử lý tiếp theo tuỳ thuộc loại dữ liệu nhận được là thông tin hay giá trị nhiệt độ. Trong trường hợp chương trình không tự động thực hiện được kết nối, người sử dụng có thể tự thực hiện kết nối khi cần thiết bằng cách gọi chương trình thực hiện kết nối mới thông qua chức năng Configure\Set port to connect của Menu chính trong chương trình. Hình 5.2 : Giao diện thiếp lập kết nối với mC 5.2. Một số chức năng chính của chương trình Sau khi kết nối được thực hiện, kết quả chuyển đổi A/D của mC sẽ được gửi liên tục sang PC. Khi nhận được dữ liệu, chương trình sẽ thực hiện phân tích dữ liệu nhận được. Nếu nhận được ký tự "#" thì hai byte dữ liệu tiếp theo sẽ được nhận dưới dạng giá trị của kết quả chuyển đổi A/D. Chương trình sẽ thực hiện hiển thị giá trị nhiệt độ vừa nhận được lên đồ thị nhiệt độ tức thời. Trong khoảng thời gian 1 phút, giá trị nhiệt độ trung bình sẽ được lưu lại cơ sở dữ liệu để có thể xử lý lại đồng thời giá trị này cũng được hiển thị trên đồ thị nhiệt độ trung bình. Hình 5.3 : Giao diện nhận và hiển thị kết quả ADC Bất kỳ byte dữ liệu nào nhận được mà trước đó chương trình không nhận được ký tự "#" đều được coi là ký tự hiển thị và sẽ được hiển thị trên cửa sổ truyền nhận thông tin giữa PC và mC. Đồng thời chương trình cũng có thể gửi một chuỗi thông tin sang mC để hiển thị trên giao diện LCD. Thao tác này có thể được thực hiện đồng thời với thao tác truyền dữ liệu của mC do vi mạch UART của mC hoạt động ở chế độ chuyền song công. Chương trình cũng có thể gửi lệnh để mC thực hiện thông qua việc lựa chọn thang nhiệt độ hiển thị là 0C hay 0K trong hộp thoại điều khiển và truyền nhận thông tin của chương trình. Hình 5.4 : Giao diện truyền nhận thông tin Ngoài các chức năng trên chương trình cũng cho phép xem lại dữ liệu được thu thập từ trước thông qua chức năng File\View data from list của Menu chương trình. Chức năng này không chỉ cho phép xem lại dữ liệu mà nó có thể dựng lại đồ thị diễn biến của nhiệt độ được lưu trong cơ sở dữ liệu theo thời gian giá trị nhiệt độ được cập nhật. Hình 5.5 : Giao diện xem lại dữ liệu được lưu trữ 5.3. Nhận xét và đánh giá. Nhìn chung, phần mềm trên máy tính và chương trình điều khiển mC chạy thử nghiệp cho kết quả tốt. Hai chương trình này hoạt động một cách đồng bộ trong việc truyền nhận dữ liệu, do đó kết nối thành một hệ thống hoàn chỉnh. Phần mềm trên PC không chỉ biểu diễn được các giá trị nhiệt độ dạng đồ thị theo thời gian mà còn có thể lưu trữ các thông tin cần thiết trong quá trình thu thập dữ liệu và các thông tin lưu trữ này có thể được xem lại khi cần thiết. Kết quả ADC được truyền sang máy tính để máy tính thực hiện các thao tác phức tạp như dựng đồ thị và lưu trữ, điều này giúp cho công việc lập trình trở nên đơn giản và đỡ tốn thời gian cũng như chi phí so với việc thực hiện công việc này trên mC. Về cơ bản mạch phần cứng đã được lắp rắp hoàn chỉnh và chạy thử cho kết quả tốt đáp ứng được yêu cầu đề ra của đồ án. Song do điều kiện về thời gian nên không kịp thiết kế mạch in theo kỹ thuật có nên cũng phần nào ảnh hưởng đến chất lượng kỹ thuật cũng như chất lượng về mặt cảm quan của sản phẩm. Ngoài ra, do kinh nghiệm trong việc thiết kế phần cứng còn nhiều hạn chế nên việc ghép nối giữa mC với các modul khác qua các cổng I/O của mC AT90S8535 chưa thực sự tối ưu. Hoạt động trao đổi dữ liệu dữ máy tính và RTU được thực hiện dựa trên phương pháp truyền thông nối tiếp theo chuẩn RS232, do đó tốc độ truyền dữ liệu bị hạn chế. Mặt khác, do dữ liệu được truyền trực tiếp từ mC tới máy tính mà không qua Modem nên khoảng cách giữa máy tính vào RTU cũng bị giới hạn. Mặc dù hệ thống cần thiết kế đã hoàn thành, tuy nhiên có thể thấy nó có một số hạn chế trong đó hạn chế lớn nhất là khả ứng dụng trong thực tế của sản phẩm không cao. Nên mặc dù việc thay đổi đại lượng biến đổi ở đầu vào của bộ chuyển đổi A/D trong hệ thống để phù hợp với các ứng dụng thực tế không đòi hỏi nhiều chi phí và thời gian thiết kế lại mạch, nhưng chương trình điều khiển mC và chương trình trên PC cần có những thay đổi thích hợp. Kết luận Trong bản báo có đồ án tốt nghiệp này, em đã nêu ra một số lý thuyết sử dụng để thiết kế và quy trình công việc phải thực hiện trong thực tế. Nói chung công việc đã hoàn thành theo đúng tiến độ đề ra, tuy nhiên do năng lực cũng như kinh nghiệm về lĩnh vực công nghệ phần cứng còn nhiều yếu kém nên đồ án không thể tránh được những thiếu sót. Tuy nhiên, trong thời gian thực hiện đồ án, em cũng đã rút ra được một số kinh nghiệm quý báu, điều này rất cần thiết cho em khi ra làm việc thực tế. Nói chung, hệ thống cần thiết kế đã hoàn thành và chạy thử nghiệp cho kết quả tốt. Do mục đích của đồ án là tìm hiểu nguyên lý hoạt động và thực hiện điều khiển một bộ vi xử lý AT90S8535, đây là một mC còn rất mới của hãng ATMEL nên sản phẩm được thiết kế hầu như không được ứng dụng trong thực tế mà chỉ mang tính thử nghiệm. Tuy nhiên, thông qua quá trình tìm hiệu và sử mC AT90S8535 để thiết kế, có thể giúp em hiểu phần nào về công nghệ phần cứng ứng dụng trong các lĩnh vực khác nhau trong cuộc sống. Sau khi hoàn thành đồ án, em sẽ tìm hiểu thêm các kiến thức về kỹ thuật phối ghép để có thể thực hiện thiết kế những mạch điện tử có khả năng ứng dụng cao trong thực tế. Một lần nữa em xin chân thành cảm ơn thầy giáo hướng dẫn Bùi Quốc Anh đã tận tình hướng dẫn và giúp đỡ em rất nhiều trong suốt thời gian thực hiện đồ án này. Em cũng xin chân thành sự giúp đỡ của các anh làm việc ở trung tâm NET.JSC đã giúp đỡ em hoàn thành bản đồ án này. Phụ lục Chương trình điều khiển mC AT90S8535 .nolist .include "\AVR\AvrAssembler\Appnotes\8535def.inc" .list ;Defined register .def Save = r1 .def HPtrTx = r2 .def LPtrTx = r3 .def HPtrRxL = r4 .def HPtrRxH = r5 .def ShowRxL = r6 .def ShowRxH = r7 .def ResultADCL = r8 .def ResultADCH = r9 .def Implement = r10 .def StatementReg = r13 .def TimeOut = r16 .def Temp = r17 .def Instr = r18 .def Data = r19 .def AddrShow = r20 .def KeyPress = r21 .def CtrlReg = r22 .def OldKey = r23 .def Position = r24 .def PositionH = r25 ;Defined control constant .equ RS = 6 ;RS signal .equ RW = 5 ;RW signal .equ E = 4 ;Enable signal ;Control KeyPad .equ Row1 = 7 .equ Row2 = 6 .equ Row3 = 5 .equ Row4 = 4 .equ Col1 = 0 .equ Col2 = 1 .equ Col3 = 2 .equ Col4 = 3 .equ INTRATE = 4 ;INT rate keypress .equ EnImpKey = 1 .equ ImpKey = 0 .equ EnSelectTxRx = 4 .equ SelectTxRx = 2 .equ EnShowRxBuff = 8 .equ ShowRxBuff = 3 .equ EnInstroduc = 2 .equ Instroduc = 1 .equ EnOnKeyPress = $80 .equ OnKeyPress = 7 .equ PressOne = 0 .equ PressTwo = $10 .equ PressThree = $20 .equ PressFour = $30 .equ CR = $0D .equ Statement = $23 ;Ascii '#' .equ EnShow_CK = $01 ;Show cencius .equ Show_CK = 0 .equ EnShowSymbolTempr = $02 ;Show symbol Tempr .equ ShowSymbolTempr = 1 .equ EnCencius = $01 ;Display temprature for cencius ;Macro get address of last char in string .macro Get_Addr_Char ldi Position,@0 ;Last position show @0 ldi Instr,@1 ;Display on line @1 ldi Temp,@2 ;Total char of string @2 ldi ZL,LOW(@3<<1) ;Name of string @3 ldi ZH,HIGH(@3<<1) adiw ZL,@2-1 ;Get address of last char in string .endmacro ;Macro get address of string .macro Get_Addr_String ldi Instr,@0 ;Position show @0 ldi @1,LOW(@3<<1) ;Low pointer @1, name's string @3 ldi @2,HIGH(@3<<1) ;High pointer @2 ldi Temp,@4 ;Total char @4 .endmacro ;Macro set first ascii code for keypress .macro Set_First_Ascii ldi Data,@0 ;Ascii of number @0 ldi Position,@1 ;Ascii of prechar @1 .endmacro ;Macro get position to display for char .macro Get_Position cpi @0,@1 ;Position to show @0, breq GetPos ;Position last @1 inc @0 GetPos: mov Instr,@0 .endmacro ;Create buffer for RxD and TxD .dseg .org $0060 TxBuff : .byte 128 ;Buffer send RxBuff : .byte 128 ;Buffer receive ;Defined constant of buffer .equ EndTxBuff = LOW(TxBuff)+127 .equ StartTxBuff = LOW(TxBuff)-1 .equ EndRxBuffL = $62 .equ EndRxBuffH = $01 .equ StartRxBuff = LOW(RxBuff) .cseg .org $000 rjmp RESET rjmp SCAN_CODE .org $006 rjmp ENABLE_ADC ;Enable ADC .org $008 rjmp KEY_RATE ;INT KEYRATE .org $00B rjmp Rx_COMPELET .org $00E rjmp END_CONVERT ;End convert ADC .org $011 PrefA1 : .db "TRUONG DHBK HA NOI" PrefA2 : .db "KHOA CNTT" PrefA3 : .db "DO AN TOT NGHIEP" PrefA4 : .db "NG.CUU IC AT90S8535" PrefB1 : .db "SINH VIEN THUC HIEN" PrefB2 : .db "VU TAN MANH" PrefB3 : .db "GIAO VIEN HUONG DAN" PrefB4 : .db "BUI QUOC ANH" Tile : .db " MEASURE TEMPERATURE" Info : .db "CURRTEMP =" Symbol : .db "Tx:" ADCon : .db "Waiting" OverTx : .db "OverB! you send?" SendTo : .db "Sending... " RESET: ldi Temp,LOW(RAMEND) ;Init Stack out SPL,Temp ldi Temp,HIGH(RAMEND) out SPH,Temp cli ;Init register Control clr CtrlReg clr StatementReg clr Implement ;Init port I/O of LCD ldi Temp,$0F ;Data lines out DDRC,Temp ldi Temp,$70 ;Control Lines (bits 4,5,6) out DDRD,Temp ;Init INT0 and LCD busy ldi Temp,$02 out PORTD,Temp ;set pullup on pin 2 rcall LCD_INIT rcall SHOW_PREFACEA rcall SHOW_PREFACEB rcall DISPLAY_INTERFACE Get_Addr_String $8B,ZL,ZH,ADCon,7 rcall SHOW_STRING ;Show string wait rcall SHOW_SELECT_TxRx ;Create port for KeyPad and int register ldi Temp,$F0 ;lower nibble input out DDRB,Temp ldi Temp,$0F ;Set pullup on lower nibble out PORTB,Temp ldi OldKey,-1 ldi AddrShow,$97 ;Preaddress to show clr KeyPress ;Init address pointer to buffer Tx clr XH ldi Temp,StartTxBuff mov LPtrTx,Temp ldi Temp,LOW(TxBuff) mov HPtrTx,Temp ;Init pointer to buffer Rx clr YH ldi YL,StartRxBuff mov HPtrRxH,YH mov HPtrRxL,YL ;Init INT of KeyPad ldi Temp,$40 out GIMSK,Temp ldi Temp,$00 ;Soure trigger INT0 at lower out MCUCR,Temp ;Init UART ldi Temp,$98 ;Enable INT Rx compelet out UCR,Temp ;8 bit data 1 stop, 1 start ldi Temp,$33 ;baud = 9600bps out UBRR,Temp clr Implement ;Init register statement ;Init Interrup comperaA match of TC1 ldi Temp,$10 out TIMSK,Temp ldi Temp,$0C ;Set value $0000 to counter out TCCR1B,Temp ;CK/256 = 31.250Hz ldi Temp,$01 ;Value for comperaA match 312 out OCR1AH,Temp ;312*(256*0,125)us = 10ms ldi Temp,$38 out OCR1AL,Temp ;Init ADC ldi Temp,$00 ;Input ADC is PA0 out ADMUX,Temp ldi Temp,$8F ;Enable single mode out ADCSR,Temp ldi Temp,-1 mov ResultADCH,Temp ;Condition show symbol Tempr clr ResultADCL sei MAIN: sbrs KeyPress,OnKeyPress ;Have a key press rjmp NoKeyPress cbr KeyPress,EnOnKeyPress ;Get real KeyPress sbrs CtrlReg,ImpKey rjmp NormalKey rcall CONTROL_KEY rjmp EndKeyPress NormalKey:rcall DISPLAY_KEY in Temp,TIFR ;Clear flag TC1 andi Temp,INTRATE out TIFR,Temp in Temp,TIMSK ;Enabl Int KeyRate sbr Temp,TOIE1 out TIMSK,Temp ldi Temp,$E7 ;Init counter for int overflow TC1 out TCNT1H,Temp ;65.536 - 6.250 = $E796 ldi Temp,$96 ;6.250*(256*0.125) = 200mS out TCNT1L,Temp EndKeyPress:in Temp,GIFR ;Clear flag INT SCAN_CODE out GIFR,Temp ldi Temp,$40 ;Enable INT SCAN_CODE out GIMSK,Temp NoKeyPress:ldi Temp,-1 cp ResultADCH,Temp brne SetShowSymbol mov Temp,StatementReg sbr Temp,EnShowSymbolTempr mov StatementReg,Temp SetShowSymbol:sbrc StatementReg,ShowSymbolTempr rcall SHOW_SYMBOL_CK tst Implement brmi SkipToBack rcall EXCUTER_FROM_PC SkipToBack:rjmp MAIN ;Program control LCD ;(RS = 0,RW = 1) LCD_BUSY: sbi PORTD,RW ;Select DR Busy: sbi PORTD,E ;Read 4 MSBs bit nop cbi PORTD,E sbis PIND,7 ;LCD Busy rjmp NoBusy sbi PORTD,E ;Ignore 4 LSBs bit nop cbi PORTD,E rjmp Busy NoBusy: sbi PORTD,E cbi PORTD,RW cbi PORTD,E ret ;Instroduction in register Intr ;(RS = 0, RW = 0) LCD_INSTR: swap Instr ;Send 4 MSB bits out PORTC,Instr nop sbi PORTD,E nop cbi PORTD,E swap Instr ;Send 4 LSB bits out PORTC,Instr nop sbi PORTD,E nop cbi PORTD,E ret ;Data in register Data ;(RS = 1, RW = 0) LCD_DATA: sbi PORTD,RS swap Data ;Send 4 MSB bits out PORTC,Data nop sbi PORTD,E nop cbi PORTD,E swap Data ;Send 4 LSB bits out PORTC,Data nop sbi PORTD,E nop cbi PORTD,E cbi PORTD,RS ret ;Init LCD LCD_INIT: ldi TimeOut,$96 ;Wait 15ms after LCD on rcall DELAY ldi Instr,$3F ;Function set rcall LCD_INSTR ldi TimeOut,$29 ;Wait 4.1ms rcall DELAY rcall LCD_INSTR ldi TimeOut,$01 ;Wait 100us rcall DELAY rcall LCD_INSTR ldi Instr,$28 ;Set 4 bits interface rcall LCD_BUSY ;on 2 line, font 5x7 dots rcall LCD_INSTR ldi Instr,$08 ;LCD off rcall LCD_BUSY rcall LCD_INSTR ldi Instr,$01 ;Reset DDRAM rcall LCD_BUSY rcall LCD_INSTR ldi Instr,$0C ;LCD on rcall LCD_BUSY rcall LCD_INSTR ldi Instr,$06 ;Set address of rcall LCD_BUSY ;DDRAM increment rcall LCD_INSTR ret ;Run char to fixed Position, char in Data ;first address in Instr RUN_TO_POS: cpi Data,$20 breq NoRun push Temp push Instr RunChar: rcall LCD_BUSY rcall LCD_INSTR rcall LCD_BUSY rcall LCD_DATA ;Show char cp Instr,Position ;Right position show breq HaltRun ldi Temp,$0A ;Wait 250ms rcall TIMEWAIT push Data ;Clear char ldi Data,$20 rcall LCD_INSTR ;Get position to clear rcall LCD_BUSY rcall LCD_DATA pop Data inc Instr ;Next position show rjmp RunChar HaltRun: pop Instr pop Temp NoRun: ret ;Run char of string, Z pointer to last char of string ;coordine in Position, line address in Instr, total char in Temp RUN_STRING: lpm ;Load char to Data mov Data,r0 rcall RUN_TO_POS sbiw ZL,1 ;Next char in string dec Position ;Next position show dec Temp ;Remain char count brne RUN_STRING ret ;Clear char of display string to end of line, char in Data ;end of line in Position, address of char to clear in Instr CLEAR_TO_POS: cpi Data,$20 breq NoClear push Instr push Temp CLRChar: push Data ;Clear char ldi Data,$20 rcall LCD_INSTR rcall LCD_BUSY rcall LCD_DATA pop Data cp Instr,Position ;End of line? breq HaltCLR inc Instr ;Next position show rcall LCD_BUSY rcall LCD_INSTR rcall LCD_BUSY rcall LCD_DATA ;Reshow char at new position ldi TimeOut,10 ;Wait 250ms rcall TIMEWAIT rjmp CLRChar HaltCLR: pop Temp pop Instr NoClear: ret ;Clear display string, Z pointer to last char of string, End of line ;in Position, address of char to clear in Instr, Totla char in Temp CLEAR_STRING: lpm ;Load char to Data mov Data,r0 rcall CLEAR_TO_POS sbiw ZL,1 ;Next char to clear dec Instr ;Next address of char to clear dec Temp ;Remain char count brne CLEAR_STRING ret ;Display notify PrefaceA SHOW_PREFACEA: Get_Addr_Char $92,$80,18,PrefA1 rcall RUN_STRING ;Display on line 1 Get_Addr_Char $CD,$C0,9,PrefA2 rcall RUN_STRING ;Display on line 2 Get_Addr_Char $A5,$94,16,PrefA3 rcall RUN_STRING ;Display on line 3 Get_Addr_Char $E7,$D4,19,PrefA4 rcall RUN_STRING ;Display on line 4 ret ;Display notify PrefaceB SHOW_PREFACEB: Get_Addr_Char $93,$92,18,PrefA1 rcall CLEAR_STRING ;Clear string on line 1 Get_Addr_Char $93,$80,19,PrefB1 rcall RUN_STRING ;Display new string on line 1 Get_Addr_Char $D3,$CD,9,PrefA2 rcall CLEAR_STRING Get_Addr_Char $CE,$C0,11,PrefB2 rcall RUN_STRING Get_Addr_Char $A7,$A5,16,PrefA3 rcall CLEAR_STRING Get_Addr_Char $A7,$94,19,PrefB3 rcall RUN_STRING Get_Addr_Char $E7,$E7,19,PrefA4 rcall CLEAR_STRING Get_Addr_Char $E3,$D4,12,PrefB4 rcall RUN_STRING ret ;Display string, position in Instr, Z pointer ;to first char of string, total char in Temp SHOW_STRING: rcall LCD_INSTR ShowNext: lpm mov Data,r0 rcall LCD_BUSY rcall LCD_DATA adiw ZL,1 dec Temp brne ShowNext ret ;Show symbol RxTx SHOW_RxTx: cpi Position,9 breq TwoChar cpi Position,10 breq ThrChar ldi Temp,1 rjmp ShowSym TwoChar: ldi Temp,2 rjmp ShowSym ThrChar: ldi Temp,3 ShowSym: ldi Instr,$94 push Temp rcall SHOW_STRING pop Temp ldi Instr,$D4 mov ZL,XL mov ZH,XH push Temp rcall LCD_BUSY rcall SHOW_STRING pop Temp cpi Temp,3 brlo EndRxTx ldi Data,$52 ;ASCII code of R rcall LCD_BUSY rcall LCD_INSTR rcall LCD_BUSY rcall LCD_DATA EndRxTx: ret ;Show interface to LCD, total char in Temp DISPLAY_INTERFACE: ldi Instr,$01 ;Clear screen rcall LCD_INSTR ldi TimeOut,49 ;Wait 4.1ms rcall DELAY ldi ZL,LOW(Tile<<1) ;String on line 1 ldi ZH,HIGH(Tile<<1) adiw ZL,19 ldi YL,LOW(Info<<1) ;String on line 2 ldi YH,HIGH(Info<<1) adiw YL,9 ldi XL,LOW(Symbol<<1) ;String on line 3,4 ldi XH,HIGH(Symbol<<1) adiw XL,2 ldi Instr,$80 ldi Temp,1 ;Total char show on line 1 ldi Position,1 ;Total char show on line 2 ReShow: push Instr push ZL push ZH push Temp rcall SHOW_STRING ;Show line 1 pop Temp cpi Temp,11 ;Show line 2 brlo ShowOne ldi Instr,$C0 push Temp mov Temp,Position mov ZL,YL mov ZH,YH rcall SHOW_STRING ;Show line 2 sbiw YL,1 ;Part of string shown on line 2 cpi Position,8 brlo ShowTwo mov ZL,XL mov ZH,XH rcall SHOW_RxTx ;Show all screen sbiw XL,1 ShowTwo: pop Temp inc Position ShowOne: pop ZH pop ZL pop Instr sbiw ZL,1 ;Part of string will show ldi TimeOut,4 ;Wait 100ms rcall TIMEWAIT inc Temp cpi Temp,21 brlo ReShow ret ;Get ascii code of keypress GET_ASCII_CODE: cpi Temp,0 breq EndGetAscii add Position,Temp mov Data,Position EndGetAscii:ret ;Find ascii code of keypress, ;ascii code contain Data FIND_ASCII_CODE: cp KeyPress,OldKey ;First time key press brne FirstPress subi CtrlReg,-$10 ;increment total time keypress cbr CtrlReg,$40 ;Get real time keypress dec AddrShow ;reshow new char dec LPtrTx ;restore new char rjmp GetTimeKey FirstPress: mov OldKey,KeyPress cbr CtrlReg,$F0 ;Reset time keypress GetTimeKey:mov Temp,CtrlReg ;Get time keypress swap Temp andi Temp,$0F cpi KeyPress,5 ;Scan code < 5 brge Key5To9 cpi KeyPress,3 brge Key3Or4 cpi KeyPress,1 brne Key0Or2 Set_First_Ascii $31,$43 ;Ascii of 1 and D rcall GET_ASCII_CODE rjmp EndFindAscii Key0Or2: cpi KeyPress,2 breq Key2 Set_First_Ascii $30,$40 rcall GET_ASCII_CODE rjmp EndFindAscii Key2: Set_First_Ascii $32,$46 rcall GET_ASCII_CODE rjmp EndFindAscii Key3Or4: cpi KeyPress,3 breq Key3 Set_First_Ascii $34,$4C rcall GET_ASCII_CODE rjmp EndFindAscii Key3: Set_First_Ascii $33,$49 rcall GET_ASCII_CODE rjmp EndFindAscii Key5To9: cpi KeyPress,7 brge Key7To9 cpi KeyPress,6 brne Key5 Set_First_Ascii $36,$52 rcall GET_ASCII_CODE rjmp EndFindAscii Key5: Set_First_Ascii $35,$4F rcall GET_ASCII_CODE rjmp EndFindAscii Key7To9: cpi KeyPress,8 brne Key7Or9 Set_First_Ascii $38,$58 cpi Temp,3 brne SkipFour cbr CtrlReg,$F0 ;Loopback times keypress ldi Temp,0 ;to skip keypress four SkipFour: rcall GET_ASCII_CODE rjmp EndFindAscii Key7Or9: cpi KeyPress,9 brne Key7 Set_First_Ascii $39,$19 cpi Temp,2 brne SkipThree cbr CtrlReg,$F0 ldi Temp,0 SkipThree: rcall GET_ASCII_CODE rjmp EndFindAscii Key7: Set_First_Ascii $37,$55 rcall GET_ASCII_CODE EndFindAscii:ret ;Display char in Tx buffer, use pointer Z ;total char to show in Temp, position show in Instr DISPLAY_CHAR_IN_TxBUFF: rcall LCD_INSTR NextShow: ld Data,Z+ rcall LCD_BUSY rcall LCD_DATA dec Temp brne NextShow ret ;Get pointer to first char show in Tx buff on LCD GET_POINTER: push Temp mov Temp,AddrShow subi Temp,$97 ;Total current char display mov Position,LPtrTx sub Position,HPtrTx cp Position,Temp breq NoGetPoint mov Position,LPtrTx sub Position,Temp mov HPtrTx,Position ;Set pointer pop Temp NoGetPoint:ret ;Display char in TxBuff to LCD ;Total char to show in Temp SHOW_CHAR_IN_TxBuff: rcall GET_POINTER cpi AddrShow,$A7 brne NoReShow cpi Temp,15 ;Number char Need to show? brne Show16Char inc HPtrTx ;Show 15 last char Show16Char:ldi Instr,$98 ;Show 16 last char clr ZL mov ZL,HPtrTx ;Get pointer to char push Data rcall DISPLAY_CHAR_IN_TxBUFF pop Data NoReShow:ret ;Show char corresponding keypress, and store char ;into TxBuff to send to PC DISPLAY_KEY: rcall FIND_ASCII_CODE inc LPtrTx ;Increment pointer buffer ldi Temp,EndTxBuff+1 cp LPtrTx,Temp ;Over TxBuff breq OverBuff ldi Temp,15 rcall SHOW_CHAR_IN_TxBuff ;Reshow 15 lastchar in buff Get_Position AddrShow,$A7 rcall LCD_INSTR ;Show char to LCD rcall LCD_BUSY rcall LCD_DATA mov XL,LPtrTx st X,Data ;Store char rjmp EndDisplay OverBuff: Get_Addr_String $98,ZL,ZH,OverTx,16 rcall SHOW_STRING dec LPtrTx ;Get back LPtrTx EndDisplay:ret ;Show symbol select on Tx or Rx SHOW_SELECT_TxRx: ldi Temp,1 sbrs CtrlReg,SelectTxRx rjmp SelectTx ldi Instr,$97 rcall CLEAR_LINE ldi Instr,$D7 rjmp ShowSymbol SelectTx: ldi Instr,$D7 rcall CLEAR_LINE ldi Instr,$97 ShowSymbol:rcall LCD_BUSY rcall LCD_INSTR ldi Data,$7E ;Symbol select rcall LCD_BUSY rcall LCD_DATA ret ;Perform function select display on Tx or Rx SELECT_TxRx: sbrs CtrlReg,SelectTxRx rjmp EnableRx cbr CtrlReg,EnSelectTxRx ;Select Tx rjmp ShowSelect EnableRx: sbr CtrlReg,EnSelectTxRx ;Select Rx ShowSelect:rcall SHOW_SELECT_TxRx ret ;Clear char at Addrshow CLEAR_CHAR_IN_LCD: ldi Temp,16 rcall SHOW_CHAR_IN_TxBuff mov Instr,AddrShow rcall LCD_INSTR ldi Data,$20 rcall LCD_BUSY rcall LCD_DATA dec AddrShow cpi AddrShow,$97 brne EndClear ldi Temp,LOW(TxBuff) cp HPtrTx,Temp breq EndClear inc AddrShow ;Yet char mov Instr,AddrShow rcall LCD_BUSY rcall LCD_INSTR dec HPtrTx mov XL,HPtrTx ld Data,X ;Get next char to show rcall LCD_BUSY rcall LCD_DATA EndClear:ret ;Perform function backspace BACK_SPACE: sbrc CtrlReg,SelectTxRx ;Selecting Rx rjmp NoPerform cpi AddrShow,$97 breq NoPerform ;No char dec LPtrTx rcall CLEAR_CHAR_IN_LCD NoPerform:ret ;Clear char in line, address start in Instr ;Total char to clear in Temp CLEAR_LINE: rcall LCD_INSTR ldi Data,$20 NextClear: rcall LCD_BUSY rcall LCD_DATA dec Temp brne NextClear ret ;Perform function clear TxRx CLEAR_Tx_OR_Rx: sbrc CtrlReg,SelectTxRx rjmp SelectRx ldi Instr,$98 ldi Temp,16 ;Total char to clear rcall CLEAR_LINE ldi Temp,LOW(TxBuff) mov HPtrTx,Temp ldi Temp,StartTxBuff mov LPtrTx,Temp ldi AddrShow,$97 rjmp HalfClear SelectRx: ldi Instr,$D8 ;Clear display line ldi Temp,16 rcall CLEAR_LINE clr YH ;Reset pointer to RxBuff ldi YL,StartRxBuff mov HPtrRxH,YH mov HPtrRxL,YL HalfClear: ret ;Display char in Rx buffer, use pointer Z ;total char to show in Temp, position show in Instr DISPLAY_CHAR_IN_RxBUFF: rcall LCD_INSTR NextDisplay:ld Data,Z+ rcall LCD_BUSY rcall LCD_DATA cpi ZL,EndRxBuffL+1 brne NoResetPoint clr ZH ldi ZL,StartRxBuff NoResetPoint:dec Temp brne NextDisplay ret ;Perform function shift right SHIFT_RIGHT: sbrc CtrlReg,SelectTxRx rjmp ShiftR_Rx cpi AddrShow,$97 breq NoShiftR ;No char mov Position,AddrShow subi Position,$98 ;Number of current char mov Temp,LPtrTx sub Temp,HPtrTx cp Temp,Position breq NoShiftR inc HPtrTx clr ZH mov ZL,HPtrTx mov Temp,LPtrTx sub Temp,HPtrTx inc Temp cpi Temp,16 ;Number char to show brge ShowAllChar push Temp ldi Temp,$A7 ;Clear part last in LCD sub Temp,AddrShow mov Instr,AddrShow inc Instr rcall CLEAR_LINE pop Temp rjmp SetAddr ShowAllChar:ldi Temp,16 SetAddr: ldi Instr,$98 rcall DISPLAY_CHAR_IN_TxBUFF rjmp NoShiftR ShiftR_Rx: cp HPtrRxL,YL breq NoShiftR ;No char in RxBuff mov Position,ShowRxL mov PositionH,ShowRxH adiw Position,15 cpi Position,EndRxBuffL+1 brlo CheckLastPoint clr PositionH subi Position,$62 ldi Temp,StartRxBuff-1 add Position,Temp CheckLastPoint:cp Position,YL breq NoShiftR mov Position,ShowRxL mov PositionH,ShowRxH adiw Position,1 cpi Position,EndRxBuffL+1 brne GetNewPoint ;Reset pointer clr PositionH ldi Position,StartRxBuff GetNewPoint:mov ShowRxL,Position ;Get new pointor mov ShowRxH,PositionH mov ZL,ShowRxL mov ZH,ShowRxH ldi Instr,$D8 ldi Temp,16 rcall DISPLAY_CHAR_IN_RxBUFF NoShiftR: ret ;Perform function shift left SHIFT_LEFT: sbrc CtrlReg,SelectTxRx rjmp ShiftL_Rx ldi Temp,LOW(TxBuff) cp HPtrTx,Temp breq NoShiftL ;No shift dec HPtrTx mov Temp,LPtrTx sub Temp,HPtrTx inc Temp ;Total char to show cpi Temp,17 brlo ShiftTxL ldi Temp,16 ShiftTxL: ldi Instr,$98 ;Position to show clr ZH mov ZL,HPtrTx rcall DISPLAY_CHAR_IN_TxBUFF rjmp NoShiftL ShiftL_Rx: cp ShowRxL,HPtrRxL breq NoShiftL mov Position,ShowRxL mov PositionH,ShowRxH sbiw Position,1 cpi Position,StartRxBuff-1 brne NoGetNewPoint ldi Position,EndRxBuffL ldi PositionH,EndRxBuffH NoGetNewPoint:mov ShowRxL,Position ;Get new pointor mov ShowRxH,PositionH ldi Temp,16 ldi Instr,$D8 mov ZL,ShowRxL mov ZH,ShowRxH rcall DISPLAY_CHAR_IN_RxBUFF NoShiftL: ret ;Perform function Send SEND_TxBUFF_TO_PC: sbrc CtrlReg,SelectTxRx ;Selecting Rx rjmp NoSend cpi AddrShow,$97 ;No char in buff breq NoSend Get_Addr_String $98,ZL,ZH,SendTo,16 rcall SHOW_STRING ldi XL,LOW(TxBuff) SendChar: ld Data,X WaitReady:sbis USR,UDRE rjmp WaitReady out UDR,Data cp XL,LPtrTx breq ClearToSend inc XL rjmp SendChar ClearToSend:rcall CLEAR_Tx_OR_Rx NoSend: ret ;Perform control key CONTROL_KEY: cbr CtrlReg,EnImpKey ;Clear confirm controlkey cpi KeyPress,13 brge Key13To15 cpi KeyPress,11 brne Key10Or12 rcall BACK_SPACE rjmp EndControlKey Key10Or12:cpi KeyPress,10 breq Key10 rcall SHIFT_LEFT rjmp EndControlKey Key10: rcall SEND_TxBUFF_TO_PC rjmp EndControlKey Key13To15:cpi KeyPress,14 breq Key14 cpi KeyPress,15 breq Key15 rcall SHIFT_RIGHT rjmp EndControlKey Key15: rcall CLEAR_Tx_OR_Rx rjmp EndControlKey Key14: rcall SELECT_TxRx EndControlKey:ldi OldKey,-1 ;Reset OldKey ret ;Service INT0 SCAN_CODE: in Save,SREG ldi KeyPress,$00 out GIMSK,KeyPress ldi TimeOut,2 ;Wait 0.2ms for settle rcall DELAY ;Find col sbis PINB,Col1 ldi KeyPress,0 sbis PINB,Col2 ldi KeyPress,4 sbis PINB,Col3 ldi KeyPress,8 sbis PINB,Col4 ldi KeyPress,12 ;invert port to find col push Temp ldi Temp,$F0 ;Lower ninble is output out DDRB,Temp ldi Temp,$0F ;Set pullup on upper out PORTB,Temp ldi TimeOut,2 ;Wait 0.2ms for settle rcall DELAY ;Find Row sbis PINB,Row1 subi KeyPress,0 sbis PINB,Row2 subi KeyPress,-1 sbis PINB,Row3 subi KeyPress,-2 sbis PINB,Row4 subi KeyPress,-3 ;Get sort KeyPress cpi KeyPress,10 brlo Normal sbr CtrlReg,EnImpKey ;Confirm Control key Normal: sbr KeyPress,EnOnKeyPress ;Confirm a key press in Temp,TIMSK ;Disable int KEY_RATE overflow sbrs Temp,TOIE1 ;Enable? rjmp HalfScanCode cbr Temp,INTRATE out TIMSK,Temp HalfScanCode:pop Temp out SREG,Save reti ;Service INT delay for reloop of keypress KEY_RATE: in Save,SREG ldi OldKey,-1 ;Reset register for compera push Temp in Temp,TIMSK cbr Temp,INTRATE out TIMSK,Temp ;Disable INT KEY_RATE pop Temp out SREG,Save reti ;Service INT Receive compelet Rx_COMPELET: in Save,SREG push Data in Data,UDR ;Get data sbrs CtrlReg,Instroduc rjmp Get_Code ;Get symbol of Statement mov Implement,Data cbr CtrlReg,EnInstroduc rjmp HalfRx Get_Code: cpi Data,Statement ;Receive symbol Statement brne RxData sbr CtrlReg,EnInstroduc rjmp HalfRx RxData: cpi Data,CR ;End of receive brne SetStore sbr CtrlReg,EnShowRxBuff ;Reques show data in Rx buff ldi Data,$7C ;Symbol "|" end of char SetStore: cpi YL,EndRxBuffL+1 brne StoreRx clr YH ;Back to head RxBuff ldi YL,StartRxBuff inc HPtrRxL ;Increment head pointer StoreRx: st Y+,Data ;Store data to RxBuff push Temp ldi Temp,StartRxBuff cp HPtrRxL,Temp breq HalfRx cpi YL,EndRxBuffL+1 brne GetHPtrRx clr HPtrRxH ;Reset pointer head RxBuff mov HPtrRxL,Temp rjmp ResetHPtrRx GetHPtrRx: mov HPtrRxL,YL ;Get pointer head RxBuff mov HPtrRxH,YH ResetHPtrRx:pop Temp HalfRx: pop Data out SREG,Save reti ;Service INT enable adc ENABLE_ADC: in Save,SREG sbi ADCSR,ADSC ;Enable convert out SREG,Save reti ;Mull result convert with content Data to divide ;Mulled in Data MULL_RESULT_CONVER: clc clr r11 mov r12,ResultADCL Mull_Data: dec Data breq HalfMull add ResultADCL,r12 adc ResultADCH,r11 rjmp Mull_Data HalfMull: ret ;Divide result convert to get temperature ;result in ResultADCH, remainde in ResultADCL ;Divider in Data DIVIDE_TO_GET_TEMPR: clr r11 sub r12,r12 LoopDivide:cp ResultADCH,r11 brne Divide cp ResultADCL,Data brlo EndDivide Divide: sub ResultADCL,Data sbc ResultADCH,r11 clc inc r12 rjmp LoopDivide EndDivide: mov ResultADCH,r12 ret ;Service INT end convert adc ;Result in ResultADCH, remainde in ResultADCL END_CONVERT: in Save,SREG in ResultADCL,ADCL in ResultADCH,ADCH lsr ResultADCH ;Get 8 bit result ror ResultADCL lsr ResultADCH ror ResultADCL push Data ldi Data,Statement SendConfirm:sbis USR,UDRE rjmp SendConfirm out UDR,Data ldi Data,$64 ;Mull result with 100 rcall MULL_RESULT_CONVER ldi Data,$FF ;Divide with 255 to get tempr rcall DIVIDE_TO_GET_TEMPR SendResult: sbis USR,UDRE rjmp SendResult out UDR,ResultADCH ;Get result push ResultADCH clr ResultADCH ;Clear upper byte ldi Data,$0A rcall MULL_RESULT_CONVER ldi Data,$FF rcall DIVIDE_TO_GET_TEMPR ldi Data,$80 cp ResultADCL,Data brlo Get_Remainder inc ResultADCH Get_Remainder:mov ResultADCL,ResultADCH pop ResultADCH SendRemainde:sbis USR,UDRE rjmp SendRemainde out UDR,ResultADCL ;Get remainder ;thay bng dung co bao rcall DISPLAY_TEMPR_TO_LCD pop Data out SREG,Save reti ;Show temperature to LCD DISPLAY_TEMPR_TO_LCD: push Instr ldi Instr,$CB rcall LCD_INSTR push ResultADCL mov ResultADCL,ResultADCH clr ResultADCH sbrs StatementReg,Show_CK rjmp ShowTemprC clr Instr ldi Data,$C8 ;Get Kelvin add ResultADCL,Data adc ResultADCH,Instr ldi Data,$49 add ResultADCL,Data adc ResultADCH,Instr ShowTemprC:ldi Data,$64 rcall DIVIDE_TO_GET_TEMPR ;Get number hundres ldi Data,0 cp ResultADCH,Data breq No100 mov Data,ResultADCH subi Data,-$30 rjmp Show100 No100: ldi Data,$20 Show100: rcall LCD_BUSY rcall LCD_DATA ldi Data,$0A clr ResultADCH rcall DIVIDE_TO_GET_TEMPR ldi Data,0 cp ResultADCH,Data breq No10 mov Data,ResultADCH rjmp Show10 No10: ldi Data,$30 Show10: rcall LCD_BUSY rcall LCD_DATA mov Data,ResultADCL subi Data,-$30 rcall LCD_BUSY rcall LCD_DATA ldi Data,$2E rcall LCD_BUSY rcall LCD_DATA pop ResultADCL mov Data,ResultADCL subi Data,-$30 rcall LCD_BUSY rcall LCD_DATA pop Instr ret ;Show symbol temperature SHOW_SYMBOL_CK: mov Temp,StatementReg cbr Temp,EnShowSymbolTempr mov StatementReg,Temp ldi Instr,$D0 rcall LCD_INSTR ldi Data,$DF rcall LCD_BUSY rcall LCD_DATA sbrs StatementReg,Show_CK rjmp ShowSymbolC ldi Data,$4B ;Ascii of K rjmp DisplaySymbol ShowSymbolC: ldi Data,$43 ;Ascii of C DisplaySymbol: rcall LCD_BUSY rcall LCD_DATA ret ;Excuter statement from PC EXCUTER_FROM_PC: ldi Temp,EnCencius cp Implement,Temp brne EnKenvin mov Temp,StatementReg cbr Temp,EnShow_CK rjmp Excuted EnKenvin: mov Temp,StatementReg sbr Temp,EnShow_CK Excuted: sbr Temp,EnShowSymbolTempr mov StatementReg,Temp ldi Temp,-1 mov Implement,Temp ret ;Program time out delay ;TimeOut delay = (0.1*TimeOut)ms DELAY: push Data push Temp Reloop: ldi Data,$03 Back: ldi Temp,$56 Loop: dec Temp brne Loop dec Data brne Back dec TimeOut brne ReLoop pop Temp pop Data ret ;TimeWait = (25*Temp)ms TIMEWAIT: ldi TimeOut,$FA rcall DELAY dec Temp brne TIMEWAIT ret

Các file đính kèm theo tài liệu này:

  • docDAN021.doc