@richey
2022-10-27T01:40:31.000000Z
字数 25329
阅读 3367
物联网创新设计实践 讲义 单片机软件设计实践https://www.zybuluo.com/richey/note/1262297
https://www.zybuluo.com/richey/note/1263469
#include <reg51.h>#include "common.h"#define FOSC 11059200ul#define T0_H (65536-(10*FOSC)/(12*1000))/256#define T0_L (65536-(10*FOSC)/(12*1000))%256uint16_t tick = 0;bit bFlag1 = 0;bit bFlag2 = 0;bit bFlag3 = 0;bit bFlag4 = 0;void initSys();sbit LED0 = P1^0;sbit LED1 = P1^1;sbit LED2 = P1^2;sbit LED3 = P1^3;void main(){initSys();while(TRUE){if(bFlag1){bFlag1 = 0;LED0 = !LED0;}if(bFlag2){bFlag2 = 0;LED1 = !LED1;}if(bFlag3){bFlag3 = 0;LED2 = !LED2;}if(bFlag4){bFlag4 = 0;LED3 = !LED3;}}}void initSys(){TMOD = 0x01;TH0 = T0_H;TL0 = T0_L;EA = 1;ET0 = 1;TR0 = 1;}void timer0() interrupt 1 {TH0 = T0_H;TL0 = T0_L;tick++;if((tick % 100) == 0){bFlag1 = 1;}if((tick % 150) == 3){bFlag2 = 1;}if((tick % 20) == 5){bFlag3 = 1;}if((tick % 300) == 7){bFlag4 = 1;}}

#include "reg51.h"#include "common.h"#define FOSC 11059200ul#define T0_H (65536-(5*FOSC)/(1000*12))/256#define T0_L (65536-(5*FOSC)/(1000*12))%256sbit COM0 = P1^0;sbit COM1 = P1^1;sbit COM2 = P1^2;sbit COM3 = P1^3;uint8_t dispBuf[] = {1,2,3,4};uint8_t code ledDeg[] = {0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82,0xF8, 0x80, 0x90};bit segFlag = 0;uint16_t counts = 0;void initSys();void updateSeg();void main(){initSys();while(1){if(segFlag){segFlag = 0;updateSeg();}}}void initSys(){TMOD = 0x01;TH0 = T0_H;TL0 = T0_L;EA = 1;ET0 = 1;TR0 = 1;}void timer0() interrupt 1{TH0 = T0_H;TL0 = T0_L;segFlag = 1;if(counts++ > 200){counts = 0;b1sFlag = 1;}}void updateSeg(){static uint8_t i = 0;P3 = 0xff; //proteus simulation needswitch(i){case 0: COM0 = 1; COM1 = 0; COM2 = 0; COM3 = 0; break;case 1: COM0 = 0; COM1 = 1; COM2 = 0; COM3 = 0; break;case 2: COM0 = 0; COM1 = 0; COM2 = 1; COM3 = 0; break;case 3: COM0 = 0; COM1 = 0; COM2 = 0; COM3 = 1; break;}P3 = ledDeg[dispBuf[i]];i++;if(i >= 4){i = 0;}}
#include "reg51.h"#include "common.h"#define FOSC 11059200ul#define T0_H (65536-(5*FOSC)/(1000*12))/256#define T0_L (65536-(5*FOSC)/(1000*12))%256sbit COM0 = P1^0;sbit COM1 = P1^1;sbit COM2 = P1^2;sbit COM3 = P1^3;uint16_t dispData = 4567;uint8_t dispBuf[] = {1,2,3,4};uint8_t code ledDeg[] = {0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82,0xF8, 0x80, 0x90};bit segFlag = 0;bit b1sFlag = 0;uint16_t counts = 0;void initSys();void updateSeg();void updateDispBuf();void main(){initSys();while(1){if(segFlag){segFlag = 0;updateSeg();}if(b1sFlag){b1sFlag = 0;if(dispData++ > 9999){dispData = 0;}updateDispBuf();}}}void initSys(){TMOD = 0x01;TH0 = T0_H;TL0 = T0_L;EA = 1;ET0 = 1;TR0 = 1;}void timer0() interrupt 1{TH0 = T0_H;TL0 = T0_L;segFlag = 1;if(counts++ > 200){counts = 0;b1sFlag = 1;}}void updateDispBuf(){uint8_t i;uint16_t tmp = dispData;for(i = 0; i < 4 ;i++){dispBuf[3-i] = tmp%10;tmp = tmp/10;}}void updateSeg(){static uint8_t i = 0;P3 = 0xff; //proteus simulation needswitch(i){case 0: COM0 = 1; COM1 = 0; COM2 = 0; COM3 = 0; break;case 1: COM0 = 0; COM1 = 1; COM2 = 0; COM3 = 0; break;case 2: COM0 = 0; COM1 = 0; COM2 = 1; COM3 = 0; break;case 3: COM0 = 0; COM1 = 0; COM2 = 0; COM3 = 1; break;}P3 = ledDeg[dispBuf[i]];i++;if(i >= 4){i = 0;}}


sbit TLC549_CS = P1^0;sbit TLC549_DOUT = P1^1;sbit TLC549_CLK = P1^6;uint8_t bdata AdValue;sbit AIN = AdValue^0;uint8_t getAdValue(){uchar i;TLC549_CS = 0;TLC549_DOUT = 1;TLC549_CLK = 0;for(i=0;i<8;i++){AdValue = AdValue<<1;TLC549_CLK = 1;_nop_();_nop_();AIN = TLC549_DOUT;TLC549_CLK = 0;_nop_();_nop_();}TLC549_CS = 1;return AdValue;}
if(adFlag){adFlag = 0;dispValue = 100*((float)getAdValue()*5.0/255.0);}

#include <reg51.h>#include <intrins.h>#include "common.h"#define FOSC 11059200ul#define T0_H (65536-(2*FOSC)/(1000*12))/256#define T0_L (65536-(2*FOSC)/(1000*12))%256sbit COM0 = P1^0;sbit COM1 = P1^1;sbit COM2 = P1^2;sbit COM3 = P1^3;sbit TLC549_CS = P1^6;sbit TLC549_DOUT = P1^5;sbit TLC549_CLK = P1^7;bit flag = 0;bit flag1 = 0;uint8_t ADcounts = 0;uint8_t dispBuf[] = {2,0,1,8};uint8_t code ledDeg[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};uint8_t bdata AdValue;sbit AIN = AdValue^0;void initSys();uint8_t getAdValue(){uint8_t i;TLC549_CS = 0;TLC549_DOUT = 1;TLC549_CLK = 0;for(i=0;i<8;i++){AdValue = AdValue<<1;TLC549_CLK = 1;_nop_();_nop_();AIN = TLC549_DOUT;TLC549_CLK = 0;_nop_();_nop_();}TLC549_CS = 1;return AdValue;}void main(){uint8_t i = 0;uint8_t j = 0;uint8_t ucAdValue=0;uint16_t uiAdValue =0;float fAdValue = 0.0;initSys();while(1){if(flag1){flag1 = 0;ucAdValue = getAdValue();fAdValue = (float)(ucAdValue*(5.0/255.0));uiAdValue= fAdValue * 1000;for(j=0;j<4;j++){dispBuf[3-j]= uiAdValue%10;uiAdValue /=10;}}if(flag){flag = 0;switch(i){case 0:COM0=0;COM1=1;COM2=1;COM3=1;break;case 1:COM0=1;COM1=0;COM2=1;COM3=1;break;case 2:COM0=1;COM1=1;COM2=0;COM3=1;break;case 3:COM0=1;COM1=1;COM2=1;COM3=0;break;}P3 = 0xff;P3 = ledDeg[dispBuf[i]];if(i==0)P3 &= 0x7f;if(++i>=4){i=0;}}}}void initSys(){TMOD &= 0xF0;TMOD |= 0x01;EA = 1;ET0 =1;TH0 = T0_H;TL0 = T0_L;TR0 = 1;}void timer0ISR()interrupt 1{TH0 = T0_H;TL0 = T0_L;flag = 1;if(ADcounts++>=40){ADcounts = 0;flag1 = 1;}}
在本节之前,我们按照协作式调度器的设计思想,通过定时器中断产生时标,在主循环中查询标志为实现驱动不同频度的周期性任务。这种方法需要我们设计不同的flag标志,配合时钟tick计数器完成,那么有没有便捷的方法实现以上功能呢?
答案是操作系统(OS)的思想,其核心是一个任务调度器,可以将不同的任务按照设计需要进行调度。实现一个单片机可用的操作系统相当复杂,同学们可以阅读一下相关的资料,比如usos/II、tiny51等嵌入式操作系统相关的文献。这些操作系统占用系统资源(RAM、ROM、CPU)较多,在51单片机上面使用受限,其学习也相对复杂。本节,我们学习一个轻量级的调度器:“小小调度器”,并应用于数字电压表软件设计。
原作者smset:
小小调度器16位版本 小小调度器 V1.1 设计原理 (讨论稿) By smset
前言:
小小调度器是一款基于 C 语言的,协作式多任务编程框架。它基于状态机原理实现,所有任务 均采用公共堆栈,具有简单小巧,易于移植的特点,非常适合于资源紧张的单片机编程使用。 小小调度器的多任务并行机制和传统的状态机的并行机制原理是想通的。
主要的区别在于:小小调度器利用了 C 语言的LINE宏,这个LINE宏,代表了源文件中 代码的行号,通过将代码行号保存到静态变量的方式,来记录程序运行的位置信息,从而使得 原来需要人工实现的状态值设计、状态变量赋值以及状态跳转的系列编程工作,大部分均由记 录行号的宏自动实现了,使得开发者可以节省很多底层的状态设计和处理的编程工作。 基于此核心原理,小小调度器设计了一个框架和宏定义,以极低的 CPU 资源代价,模拟了一个 和真实 RTOS 系统相似的多任务编程环境,使得编程者可以用更自然、更优雅、更易于理解的方 式,来编写多任务并行代码,把时间和精力,更多的放在应用业务层逻辑的代码实现上。
特点
#include <stc89c51.h>/****小小调度器开始**********************************************/#define MAXTASKS 3volatile unsigned char timers[MAXTASKS];#define _SS \static unsigned char _lc = 0; \switch (_lc) { \default:#define _EE \; \} \; \_lc = 0; \return 255;#define WaitX(tickets) \do { \_lc = (__LINE__ % 255) + 1; \return tickets; \} while (0); \case (__LINE__ % 255) + 1:#define RunTask(TaskName, TaskID) \do { \if (timers[TaskID] == 0) \timers[TaskID] = TaskName(); \} while (0);#define RunTaskA(TaskName, TaskID) \{ \if (timers[TaskID] == 0) { \timers[TaskID] = TaskName(); \continue; \} \} //前面的任务优先保证执行#define CallSub(SubTaskName) \do { \unsigned char currdt; \_lc = (__LINE__ % 255) + 1; \return 0; \case (__LINE__ % 255) + 1: \currdt = SubTaskName(); \if (currdt != 255) \return currdt; \} while (0);#define InitTasks() \{ \unsigned char i; \for (i = MAXTASKS; i > 0; i--) \timers[i - 1] = 0; \}#define UpdateTimers() \{ \unsigned char i; \for (i = MAXTASKS; i > 0; i--) { \if ((timers[i - 1] != 0) && (timers[i - 1] != 255)) \timers[i - 1]--; \} \}#define SEM unsigned int//初始化信号量#define InitSem(sem) sem = 0;//等待信号量#define WaitSem(sem) \do { \sem = 1; \WaitX(0); \if (sem > 0) \return 1; \} while (0);//等待信号量或定时器溢出, 定时器tickets 最大为0xFFFE#define WaitSemX(sem, tickets) \do { \sem = tickets + 1; \WaitX(0); \if (sem > 1) { \sem--; \return 1; \} \} while (0);//发送信号量#define SendSem(sem) \do { \sem = 0; \} while (0);/*****小小调度器结束*******************************************************/sbit LED1 = P2 ^ 1;sbit LED2 = P2 ^ 2;sbit LED0 = P2 ^ 5;unsigned char task0() {_SS while (1) {WaitX(50);LED0 = !LED0;}_EE}unsigned char task1() {_SS6 while (1) {WaitX(100);LED1 = !LED1;}_EE}unsigned char task2() {_SS while (1) {WaitX(100);LED2 = !LED2;}_EE}void InitT0() {TMOD = 0x21;IE |= 0x82;TL0 = 0Xff;TH0 = 0XDB;TR0 = 1;}void INTT0(void) interrupt 1 using 1 {TL0 = 0Xff; // 10ms 重装TH0 = 0XDB;UpdateTimers();RunTask(task0, 0); //任务0具有精确按时获得执行的权限,要求:task0每次执行消耗时间<0.5个//ticket}void main() {InitT0();InitTasks(); //初始化任务,实际上是给timers清零while (1) {// RunTask(task0,0);RunTaskA(task1, 1); //任务1具有比任务2高的运行权限RunTaskA(task2, 2); //任务2具有低的运行权限}}复制代码
//xxsch.h#ifndef __XXSCH_H#define __XXSCH_H#define MAXTASKS 16#define BITS 16#define SEM unsigned int#if (BITS==8)#define TASK unsigned char#define TICKET_MAX 0xFF#endif#if (BITS==16)#define TASK unsigned short#define TICKET_MAX 0xFFFF#endif#if (BITS==32)#define TASK unsigned long#define TICKET_MAX 0xFFFFFFFF#endif#define _SS static unsigned char _lc=0; switch(_lc){default:#define _EE ;}; _lc=0; return TICKET_MAX;#define WaitX(tickets) do { _lc=(__LINE__%255)+1; return (tickets) ;case (__LINE__%255)+1:;} while(0);#define WaitUntil(A) do { while(!(A)) WaitX(1);} while(0);#define WAITUNTIL(A,VAL) do { WaitX(1);} while((A)!=VAL);#define WaitUntilR(A) do { while(!(A)) WaitX(0);} while(0);#define WAITUNTILR(A,VAL) do { WaitX(0);} while((A)!=VAL);#define RunTask(TaskName,TaskID) do { if (timers[TaskID]==0) { TASK d=TaskName(); while(timers[TaskID]!=d) timers[TaskID]=d;} } while(0);#define RunTaskA(TaskName,TaskID) do { if (timers[TaskID]==0) {TASK d=TaskName(); while(timers[TaskID]!=d) timers[TaskID]=d; continue;} }while(0);#define CallSub(SubTaskName) do {TASK currdt; _lc=(__LINE__%255)+1; return 0; case (__LINE__%255)+1: currdt=SubTaskName(); if(currdt!=TICKET_MAX) return currdt;} while(0);#define CallSub1(SubTaskName,p1) do {TASK currdt; _lc=(__LINE__%255)+1; return 0; case (__LINE__%255)+1: currdt=SubTaskName(p1); if(currdt!=TICKET_MAX) return currdt;} while(0);#define CallSub2(SubTaskName,p1,p2) do {TASK currdt; _lc=(__LINE__%255)+1; return 0; case (__LINE__%255)+1: currdt=SubTaskName(p1,p2); if(currdt!=TICKET_MAX) return currdt;} while(0);#define InitTasks() do {unsigned char i; for(i=MAXTASKS;i>0 ;i--) timers[i-1]=0; } while(0);#define UpdateTimers() do{unsigned char i; for(i=MAXTASKS;i>0 ;i--){if((timers[i-1]!=0)&&(timers[i-1]!=TICKET_MAX)) timers[i-1]--;}} while(0);#define InitSem(sem) do{sem=0;}while(0);#define WaitSem(sem) do{ sem=1; WaitX(0); if (sem>0) return 1;} while(0);#define SendSem(sem) do {sem=0;} while(0);#define WaitSemX(sem, tickets) do{sem=tickets+1;WaitX(0);if(sem>1){sem--;return 1;}}while (0);#endif
//main.h#ifndef __MAIN_H#define __MAIN_H#include "STC15Fxxxx.h"#define OSC_FREQ (11059200UL)#define OSC_PER_INST (12)#define BAUD 9600#define T1_H (256-OSC_FREQ/12/32/BAUD)#define T0_H (65536-(5*OSC_FREQ)/(1000*12))/256#define T0_L (65536-(5*OSC_FREQ)/(1000*12))%256typedef unsigned char uint8_t;typedef unsigned int uint16_t;typedef unsigned long uint32_t;typedef char int8_t;typedef int int16_t;typedef long int32_t;// Misc #defines#ifndef TRUE#define FALSE 0#define TRUE (!FALSE)#endif#include "xxsch.h"#endif
//main.c#include "main.h"#include "adc.h"#include "ledseg.h"#include "xxsch.h"#include "key.h"volatile TASK timers[MAXTASKS];//TASK ledseg_task();//TASK adc_task();TASK update_disp_buf_task();float g_temperature = 25.2;float g_humidity = 57.3;float g_voltage = 3.234;extern void update_ledseg_buf(float dispData, uint8_t pointsNum);void initSys();extern uint8_t key_value;void main(void) {initSys();InitTasks();while (1) {RunTaskA(ledseg_task, 8);RunTaskA(adc_task, 6);RunTaskA(key_scan_task, 2);RunTaskA(update_disp_buf_task, 4);}}void initSys() {TMOD = 0x21;TH0 = T0_H;TL0 = T0_L;TH1 = T1_H;TL1 = T1_H;EA = 1;ET0 = 1;SCON = 0x50;EA = 1;ET0 = 1;ES = 1;TR0 = 1;TR1 = 1;}void timer0_isr(void) interrupt 1 using 1 {TL0 = T0_L;TH0 = T0_H;UpdateTimers();}void update_disp_buf() {switch (key_value) {case 0:update_ledseg_buf(g_voltage, 3);break;case 1:update_ledseg_buf(g_temperature, 1);break;case 2:update_ledseg_buf(g_humidity, 1);break;}}TASK update_disp_buf_task() {_SS while (1) {WaitX(100);update_disp_buf();}_EE}
//port.h#ifndef __PORT_H#define __PORT_H// ------ ledseg.c------------------------------------------------// LED connection requires 12 port pins#define LED_DATA_PORT (P2)/* Connections to LED_DATA_PORT - See Figure 21.6 for detailsDP G F E D C B A = LED display pins| | | | | | | |x.7 x.6 x.5 x.4 x.3 x.2 x.1 x.0 = Port pinsx.7 == LED_DATA_PORT^7, etcLED codes (NB - positive logic assumed here)0 = abcdef => 00111111 = 0x3F1 = bc => 00000110 = 0x062 = abdeg => 01011011 = 0x5B3 = abcdg => 01001111 = 0x4F4 = bcfg => 01100110 = 0x665 = acdfg => 01101101 = 0x6D6 = acdefg => 01111101 = 0x7D7 = abc => 00000111 = 0x078 = abcdefg => 01111111 = 0x7F9 = abcdfg => 01101111 = 0x6FTo display decimal point, add 10 (decimal) to the above values */// Any combination of (4) pins on any ports may be used heresbit LED_DIGIT_0 = P1^0;sbit LED_DIGIT_1 = P1^1;sbit LED_DIGIT_2 = P1^2;sbit LED_DIGIT_3 = P1^3;#endif
//ledseg.c#include "main.h"#include "port.h"#include "ledseg.h"// ------ Public variable definitions ------------------------------// Lookup table - stored in code area// See Port.H for connections and code detailsuint8_t code LED_Table_G[20] =// 0 1 2 3 4 5 6 7 8 9{0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F,// 0. 1. 2. 3. 4. 5. 6. 7. 8. 9.0xBF, 0x86, 0xDB, 0xCF, 0xE6, 0xED, 0xFD, 0x87, 0xFF, 0xEF};// Global data formatted for display (initially 0,0,0,0)uint8_t LED_Mx4_Data_G[4] = {0x3F,0x3F,0x3F,0x3F};uint8_t idata point_pos = 0;static uint8_t idata Digit_G;void update_ledseg(void){//only proteus simulation need the following line!!!LED_DATA_PORT = 0xff;// Increment the digit to be displayedif (++Digit_G == LED_NUM_DIGITS){Digit_G = 0;}// Allows any pins to be usedswitch (Digit_G){case 0:{LED_DIGIT_0 = 0;LED_DIGIT_1 = 0;LED_DIGIT_2 = 0;LED_DIGIT_3 = 1;break;}case 1:{LED_DIGIT_0 = 0;LED_DIGIT_1 = 0;LED_DIGIT_2 = 1;LED_DIGIT_3 = 0;break;}case 2:{LED_DIGIT_0 = 0;LED_DIGIT_1 = 1;LED_DIGIT_2 = 0;LED_DIGIT_3 = 0;break;}case 3:{LED_DIGIT_0 = 1;LED_DIGIT_1 = 0;LED_DIGIT_2 = 0;LED_DIGIT_3 = 0;}}LED_DATA_PORT = 255 - LED_Mx4_Data_G[Digit_G];if(Digit_G == (point_pos) && Digit_G !=0){LED_DATA_PORT &= 0x7f;}}void update_ledseg_buf(float dispData, uint8_t pointsNum){uint16_t u16Value;uint8_t j;switch(pointsNum){case 0:u16Value = (uint16_t)dispData;break;case 1:u16Value = (uint16_t)(dispData * 10);break;case 2:u16Value = (uint16_t)(dispData *100);break;case 3:u16Value = (uint16_t)(dispData *1000);break;}for( j=0;j<4;j++){LED_Mx4_Data_G[j]= LED_Table_G[u16Value%10];u16Value /=10;}point_pos = pointsNum;}TASK ledseg_task() {_SS while (1) {WaitX(1);update_ledseg();}_EE}
//adc.c#include "Main.h"#include "Port.h"#include <intrins.h>#include "adc.h"sbit TLC549_DOUT = P1 ^ 5;sbit TLC549_CS = P1 ^ 6;sbit TLC549_CLK = P1 ^ 7;uint8_t bdata ad_value;sbit AIN = ad_value ^ 0;extern updateLed(float dispData, uint8_t pointsNum);extern float g_voltage;// uint8_t current_ad_value;uint8_t tlc549_adc() {uint8_t i;TLC549_CS = 0;TLC549_DOUT = 1;TLC549_CLK = 0;for (i = 0; i < 8; i++) {ad_value = ad_value << 1;TLC549_CLK = 1;_nop_();_nop_();AIN = TLC549_DOUT;TLC549_CLK = 0;_nop_();_nop_();}TLC549_CS = 1;return ad_value;}void get_ad(void) {uint8_t value;value = tlc549_adc();g_voltage = (float)(value * (5.0 / 255.0));}TASK adc_task() {_SS while (1) {WaitX(20);get_ad();}_EE}
//key.c#include "main.h"#include "key.h"sbit KEY1 = P3 ^ 5;uint8_t key_value = 0;void key_scan() ;TASK key_scan_task() {_SS while (1) {WaitX(5);key_scan();}_EE}static void key_scan() {static uint8_t _status = 0;switch (_status) {case 0:if (KEY1 == 0) {_status = 1;}break;case 1:if (KEY1 == 0) {_status = 2;} else {_status = 0;}break;case 2:if (KEY1 == 1) {_status = 3;}break;case 3:if (KEY1 == 1) {_status = 0;if (++key_value >= 3) {key_value = 0;}} else {_status = 0;}break;}}






| SM0 | SM1 | 方式 | 功 能 说 明 |
|---|---|---|---|
| 0 | 0 | 0 | 同步移位寄存器方式(用于扩展I/O口) |
| 0 | 1 | 1 | 8位异步收发,波特率可变(由定时器控制) |
| 1 | 0 | 2 | 9位异步收发,波特率为fosc/64或fosc/32 |
| 1 | 1 | 3 | 9位异步收发,波特率可变(由定时器控制) |

同步移位寄存器输入/输出方式,常用于外接移位寄存器,以扩展并行I/O口。8位数据为一帧,不设起始位和停止位,先发送或接收最低位。波特率固定为fosc/12。帧格式如下:



#define FOSC 11059200ul#define BAUD 9600#define T1_H 256-FOSC/12/32/BAUD#define T1_L 256-FOSC/12/32/BAUD#define T0_H (65536-(FOSC*50)/(12*1000))/256#define T0_L (65536-(FOSC*50)/(12*1000))%256void initSys(){SCON = 0x50; //8位异步方式,允许接收TMOD = 0x21; //T0方式1,T1方式2TH1 = T1_H;TL1 = T1_L;TH0 = T0_H;TL0 = T0_L;EA = 1;ET0 = 1;ES = 1;TR0 = 1;TR1 = 1;}
//串口查询方式发送1个字节数据void SendChar(uint8_t u8Data){SBUF = u8Data; //启动发送(注意串口是低速设备,只是启动发送并没有发送完成!)while(!TI);//等待发送完成TI = 0; //只要执行到此处,说明发送完成了(TI为1),将TI清零以免下次无法发送。}uint8_t buf;bit bRecvFalg = 0 ;//中断方式接收void serialIsr() interrupt 4{if(RI){ //如果是接收引起的中断执行这里RI = 0;//手工清零buf = SBUF;bRecvFalg = 1;//置接收标志为1}}
#include <reg51.h>#include "common.h"#define FOSC 11059200ul#define BAUD 9600#define T1_H 256-FOSC/12/32/BAUD#define T1_L 256-FOSC/12/32/BAUD#define T0_H (65536-(50*FOSC)/(12*1000))/256#define T0_L (65536-(50*FOSC)/(12*1000))%256bit b1sFlag = 0;bit bRecvFlag = 0;uint8_t u8SendData[]="Hello MCS-51\r\n";void SendChar(uint8_t u8Data);void initSys();void main(){uint8_t i;initSys();while(1){if(b1sFlag){b1sFlag = 0;for(i=0;i<(sizeof(u8SendData)-1);i++){SendChar(u8SendData[i]);}}if(bRecvFlag){bRecvFlag= 0;SendChar('B');}}}void initSys(){TMOD = 0x21;SCON = 0x50;TH0 = T0_H;TL0 = T0_L;TH1 = T1_H;TL1 = T1_L;EA = 1;ET0 = 1;ES = 1;TR0 = 1;TR1 = 1;}void Timer0Isr() interrupt 1{static uint8_t counts = 0;TH0 = T0_H;TL0 = T0_L;if(counts++>=20){counts = 0;b1sFlag =1;}}void uartIsr()interrupt 4{uint8_t recvData;if(RI){RI = 0 ;recvData = SBUF;if(recvData == 'A'){bRecvFlag = 1;}}}//串口查询方式发送1个字节数据void SendChar(uint8_t u8Data){SBUF = u8Data; //启动发送(注意串口是低速设备,只是启动发送并没有发送完成!)while(!TI);//等待发送完成TI = 0;//只要执行到此处,说明发送完成了(TI为1),将TI清零以免下次无法发送。}

| 帧头 | 地址 | 命令码 | 数据域 | 校验和 | 帧尾 |
|---|---|---|---|---|---|
| head | addr | cmd | data0-datan | checksum | end |
| '@' | '0''1' | 'D' | '1''2''3''4' | '1''0' | '\r''\n' |
| 40H | 30H31H | 44H | 31H32H33H34H | 31H30H | 0D0A |
"@01D123410\r\n"
应答帧"@01MXXXXCC\r\n"(CCCC为电压值,16进制表达,CC为校验和)
#include <reg51.h>#include <stdlib.h>#include <stdio.h>#include <intrins.h>#include "common.h"#define FOSC 11059200ul#define BAUD 9600#define T1_H (256-FOSC/12/32/BAUD)#define T0_H (65536-(50*FOSC)/(12*1000))/256#define T0_L (65536-(50*FOSC)/(12*1000))%256uint16_t sendData = 3124;uint8_t u8SendData1[]="@01D000000\r\n";uint8_t recvBuf[32] = {0};uint8_t recvIndex = 0;void initSys();void SendChar(uint8_t u8Data);bit b1sFlag = 0;bit bRecvFlag = 0;sbit TLC549_CS = P1^1;sbit TLC549_DOUT = P1^0;sbit TLC549_CLK = P1^2;uint8_t bdata AdValue;sbit AIN = AdValue^0;uint8_t getAdValue(){uint8_t i;TLC549_CS = 0;TLC549_DOUT = 1;TLC549_CLK = 0;for(i=0;i<8;i++){TLC549_CLK = 1;_nop_();_nop_();AdValue = AdValue<<1;AIN = TLC549_DOUT;TLC549_CLK = 0;_nop_();_nop_();}TLC549_CS = 1;return AdValue;}void main(){uint8_t i;int8_t i8Buf[5];initSys();while(1){if(b1sFlag){b1sFlag = 0;sendData = (uint16_t)((5.0/255.0) * (float)getAdValue()*1000);}if(bRecvFlag){bRecvFlag = 0;sprintf(i8Buf,"%04x",sendData);u8SendData1[4] = i8Buf[0];u8SendData1[5] = i8Buf[1];u8SendData1[6] = i8Buf[2];u8SendData1[7] = i8Buf[3];for(i=0; i<(sizeof(u8SendData1)-1);i++){SendChar(u8SendData1[i]);}}}}void initSys(){TMOD = 0x21;TH0 = T0_H;TL0 = T0_L;TH1 = T1_H;TL1 = T1_H;SCON = 0x50;EA = 1;ET0 = 1;ES = 1;TR0 = 1;TR1 = 1;}void timer0Isr() interrupt 1{static uint8_t counts = 0;TH0 = T0_H;TL0 = T0_L;if(counts++ >= 20){counts =0;b1sFlag = 1;}}void serialIsr()interrupt 4{uint8_t recvData;if(RI){RI = 0;recvData = SBUF;if(recvData == '@'){recvIndex = 0;}if(recvIndex <31){recvBuf[recvIndex++] = recvData;}else{recvIndex = 0;}if(recvData == '\n'){bRecvFlag = 1;}}}//串口查询方式发送1个字节数据void SendChar(uint8_t u8Data){SBUF = u8Data; //启动发送(注意串口是低速设备,只是启动发送并没有发送完成!)while(!TI);//等待发送完成TI = 0; //只要执行到此处,说明发送完成了(TI为1),将TI清零以免下次无法发送。}



#include "reg51.h"#include <intrins.h>#include <stdlib.h>#include <stdio.h>#include "common.h"#define FOSC 11059200ul#define BAUD 9600#define T1_H (256-FOSC/12/32/BAUD)#define T0_H (65536-(2*FOSC)/(1000*12))/256#define T0_L (65536-(2*FOSC)/(1000*12))%256sbit COM0 = P1^0;sbit COM1 = P1^1;sbit COM2 = P1^2;sbit COM3 = P1^3;sbit DO1 = P3^2;sbit TLC549_CS = P1^6;sbit TLC549_DOUT = P1^5;sbit TLC549_CLK = P1^7;bit flag = 0;bit flag1 = 0;uint8_t ADcounts = 0;uint8_t dispBuf[] = {2,0,1,8};uint8_t code ledDeg[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};uint8_t bdata AdValue;sbit AIN = AdValue^0;uint16_t sendData = 3124;uint8_t u8SendData1[]="@12D00001111222200\r\n";uint8_t code u8SendData2[]="$12$\r\n";uint8_t idata recvBuf[16] = {0};uint8_t recvIndex = 0;void initSys();void SendChar(uint8_t u8Data);bit bRecvFlag = 0;uint8_t getAdValue(){uint8_t i;TLC549_CS = 0;TLC549_DOUT = 1;TLC549_CLK = 0;for(i=0;i<8;i++){AdValue = AdValue<<1;TLC549_CLK = 1;_nop_();_nop_();AIN = TLC549_DOUT;TLC549_CLK = 0;_nop_();_nop_();}TLC549_CS = 1;return AdValue;}void main(){uint8_t i = 0;uint8_t j = 0;uint8_t ucAdValue=0;uint16_t uiAdValue =0;float fAdValue = 0.0;int8_t i8Buf[5];initSys();while(1){if(flag1){flag1 = 0;ucAdValue = getAdValue();fAdValue = (float)(ucAdValue*(5.0/255.0));uiAdValue= fAdValue * 1000;sendData = uiAdValue;for(j=0;j<4;j++){dispBuf[3-j]= uiAdValue%10;uiAdValue /=10;}}if(flag){flag = 0;P2 = 0xff;switch(i){case 0:COM0=1;COM1=0;COM2=0;COM3=0;break;case 1:COM0=0;COM1=1;COM2=0;COM3=0;break;case 2:COM0=0;COM1=0;COM2=1;COM3=0;break;case 3:COM0=0;COM1=0;COM2=0;COM3=1;break;}P2 = ledDeg[dispBuf[i]];if(i==0)P2 &= 0x7f;if(++i>=4){i=0;}}if(bRecvFlag){bRecvFlag = 0;if(recvBuf[0] == '$'){for(i=0; i<(sizeof(u8SendData2)-1);i++){SendChar(u8SendData2[i]);}}if(recvBuf[0] == '@'){if(recvBuf[3] == 'd'){sprintf(i8Buf,"%04x",sendData);u8SendData1[4] = i8Buf[0];u8SendData1[5] = i8Buf[1];u8SendData1[6] = i8Buf[2];u8SendData1[7] = i8Buf[3];u8SendData1[8] = i8Buf[0];u8SendData1[9] = i8Buf[1];u8SendData1[10] = i8Buf[2];u8SendData1[11] = i8Buf[3];u8SendData1[12] = i8Buf[0];u8SendData1[13] = i8Buf[1];u8SendData1[14] = i8Buf[2];u8SendData1[15] = i8Buf[3];for(i=0; i<(sizeof(u8SendData1)-1);i++){SendChar(u8SendData1[i]);}}if(recvBuf[3] == 'f'){if(recvBuf[7] == '1'){DO1 = 0;}if(recvBuf[7] == '0'){DO1 = 1;}}}}}}void initSys(){TMOD = 0x21;TH0 = T0_H;TL0 = T0_L;TH1 = T1_H;TL1 = T1_H;EA = 1;ET0 =1;SCON = 0x50;EA = 1;ET0 = 1;ES = 1;TR0 = 1;TR1 = 1;}void timer0ISR()interrupt 1{TH0 = T0_H;TL0 = T0_L;flag = 1;if(ADcounts++>=40){ADcounts = 0;flag1 = 1;}}void serialIsr()interrupt 4{uint8_t recvData;if(RI){RI = 0;recvData = SBUF;if(recvData == '@' || recvData == '$'){recvIndex = 0;}if(recvIndex <31){recvBuf[recvIndex++] = recvData;}else{recvIndex = 0;}if(recvData == '\n'){bRecvFlag = 1;}}}void SendChar(uint8_t u8Data){SBUF = u8Data;while(!TI);TI = 0;}