本系統是一個基于51單片機的雙核系統設計。采用單片機型號STC12C60S2,使用串口作為數據總線,占用兩個io作為控制總線。例程是驅動LCD1602,用一個單片機P0口的低四位驅動1602dat口的高四位,另一個單片機P0口低四位驅動1602dat口的高四位。顯示內容為兩個12單片機的P1.0采集電位器的電壓量。同時第二個單片機輸出硬件pwm。其實也不能說是雙核吧,但是時序配合必須很好,不然1602驅動不起來從核只需要對硬件初始化和io口操作,邏輯在主核實現,然后傳給從核,從核處理后對相應io口操作。
不能發視頻就很尷尬。
貼出代碼,感興趣的朋友可以試下。需要說明的是,PWM可以通過數據總線傳給第二個單片機的,改天試試。有想法的朋友可以交流下。
畫重點!敲黑板!
我做這個完全處于興趣,覺得沒什么用的可以劃走了。
接下來的計劃是做一個四核系統。
制作出來的實物圖如下:
51hei圖片_20220729223909.jpg (380.77 KB, 下載次數: 43)
下載附件
2022-7-29 22:39 上傳
51hei圖片_20220729223853.jpg (602.28 KB, 下載次數: 43)
下載附件
2022-7-29 22:39 上傳
主
/*************** 用戶定義參數 *****************************/
#define MAIN_Fosc 22118400L //define main clock
#define Baudrate1 9600 //define the baudrate, 如果使用BRT做波特率發生器,則波特率跟串口2一樣
//12T mode: 600~115200 for 22.1184MHZ, 300~57600 for 11.0592MHZ
#define Baudrate2 9600 //define the baudrate2,
//12T mode: 600~115200 for 22.1184MHZ, 300~57600 for 11.0592MHZ
#define BUF_LENTH 128 //定義串口接收緩沖長度
/**********************************************************/
#include<reg51.h>
#include<intrins.h> //包含_nop_()函數定義的頭文件
#include<fun.h>
sfr AUXR1 = 0xA2;
sfr AUXR = 0x8E;
sfr S2CON = 0x9A; //12C5A60S2雙串口系列
sfr S2BUF = 0x9B; //12C5A60S2雙串口系列
sfr IE2 = 0xAF; //STC12C5A60S2系列
sfr BRT = 0x9C;
unsigned char uart1_wr=0; //寫指針
unsigned char uart1_rd=0; //讀指針
unsigned char xdata RX1_Buffer[BUF_LENTH];
bit B_TI;
unsigned char uart2_wr=0; //寫指針
unsigned char uart2_rd=0; //讀指針
unsigned char xdata RX2_Buffer[BUF_LENTH];
bit B_TI2;
/****************** 編譯器自動生成,用戶請勿修改 ************************************/
#define T1_TimerReload (256 - MAIN_Fosc / 192 / Baudrate1) //Calculate the timer1 reload value at 12T mode
#define BRT_Reload (256 - MAIN_Fosc / 12 / 16 / Baudrate2) //Calculate BRT reload value
#define TimeOut1 (28800 / (unsigned long)Baudrate1 + 2)
#define TimeOut2 (28800 / (unsigned long)Baudrate2 + 2)
#define TI2 (S2CON & 0x02) != 0
#define RI2 (S2CON & 0x01) != 0
#define CLR_TI2() S2CON &= ~0x02
#define CLR_RI2() S2CON &= ~0x01
/******LCD1602***********/
sbit p00=P0^0;
sbit p01=P0^1;
sbit p02=P0^2;
sbit p03=P0^3;
sbit p04=P0^4;
sbit p05=P0^5;
sbit p06=P0^6;
sbit RS=P2^6; //寄存器選擇位,將RS位定義為P2.6引腳
sbit RW=P2^5; //讀寫選擇位,將RW位定義為P2.5引腳
sbit E=P2^7; //使能信號位,將E位定義為P2.7引腳
sbit BF=P0^7; //忙碌標志位,,將BF位定義為P0.7引腳
sbit tx=P2^0; //從機狀態線
sbit rx=P2^1; //從機狀態線
unsigned char flag1,flag2,flag3,flag4;//發送指令位的值
unsigned char string[ ]={"Core1: V "},string2[ ]={"Core2: V "};
/*****************ADC配置*************************/
sfr P1ASF = 0x9D; //12C5A60AD/S2系列模擬輸入(AD或LVD)選擇
sfr ADC_CONTR = 0xBC; //帶AD系列
sfr ADC_RES = 0xBD; //帶AD系列
sfr ADC_RESL = 0xBE; //帶AD系列
// 7 6 5 4 3 2 1 0 Reset Value
//sfr ADC_CONTR = 0xBC; ADC_POWER SPEED1 SPEED0 ADC_FLAG ADC_START CHS2 CHS1 CHS0 0000,0000 //AD 轉換控制寄存器
#define ADC_OFF() ADC_CONTR = 0
#define ADC_ON (1 << 7)
#define ADC_90T (3 << 5)
#define ADC_180T (2 << 5)
#define ADC_360T (1 << 5)
#define ADC_540T 0
#define ADC_FLAG (1 << 4) //軟件清0
#define ADC_START (1 << 3) //自動清0
#define ADC_CH0 0
#define ADC_CH1 1
#define ADC_CH2 2
#define ADC_CH3 3
#define ADC_CH4 4
#define ADC_CH5 5
#define ADC_CH6 6
#define ADC_CH7 7
unsigned int adc10_start(unsigned char channel); //channel = 0~7
double adc;
/********************PWM******************************/
#define PCA_IDLE_DISABLE 0 //1: MCU在IDLE模式時禁止PCA工作。 0: MCU在IDLE模式時允許PCA工作。
#define PCA_SOURCE_SELECT 4 //選擇PCA的基準時鐘源。
//0:系統時鐘Fosc/12。
//1:系統時鐘Fosc/2。
//2:定時器0的溢出。
//3:ECI/P3.4腳的外部時鐘輸入(最大=Fosc/2)。
//4:系統時鐘Fosc。
//5:系統時鐘Fosc/4。
//6:系統時鐘Fosc/6。
//7:系統時鐘Fosc/8。
sfr CCON = 0xD8;
sfr CMOD = 0xD9;
sfr CCAPM0 = 0xDA; //PCA module 0 work mode
sfr CCAPM1 = 0xDB; //PCA module 1 work mode
sfr CL = 0xE9; //PCA counter
sfr CCAP0L = 0xEA; //PCA模塊0的捕捉/比較寄存器低8位。
sfr CCAP1L = 0xEB; //PCA模塊1的捕捉/比較寄存器低8位。
sfr PCA_PWM0 = 0xF2; //PCA模塊0 PWM寄存器。
sfr PCA_PWM1 = 0xF3; //PCA模塊1 PWM寄存器。
sfr CH = 0xF9;
sfr CCAP0H = 0xFA; //PCA模塊0的捕捉/比較寄存器高8位。
sfr CCAP1H = 0xFB; //PCA模塊1的捕捉/比較寄存器高8位。
sbit CCF0 = CCON^0; //PCA 模塊0中斷標志,由硬件置位,必須由軟件清0。
sbit CCF1 = CCON^1; //PCA 模塊1中斷標志,由硬件置位,必須由軟件清0。
sbit CR = CCON^6; //1: 允許PCA計數器計數,必須由軟件清0。
sbit CF = CCON^7; //PCA計數器溢出(CH,CL由FFFFH變為0000H)標志。PCA計數器溢出后由硬件置位,必須由軟件清0。
#define PWM0_NORMAL() PCA_PWM0 = 0 //PWM0正常輸出(默認)
#define PWM0_OUT_0() PCA_PWM0 = 3 //PWM0一直輸出0
#define PWM1_NORMAL() PCA_PWM1 = 0 //PWM1正常輸出(默認)
#define PWM1_OUT_0() PCA_PWM1 = 3 //PWM1一直輸出0
/*****************************************************
函數功能:延時1ms
(3j+2)*i=(3×33+2)×10=1010(微秒),可以認為是1毫秒
***************************************************/
void delay1ms()
{
unsigned char i,j;
for(i=0;i<10;i++)
for(j=0;j<33;j++)
;
}
/*****************************************************
函數功能:延時若干毫秒
入口參數:n
***************************************************/
void delay(unsigned char n)
{
unsigned char i;
for(i=0;i<n;i++)
delay1ms();
}
/*****************************************************
函數功能:判斷液晶模塊的忙碌狀態
返回值:result。result=1,忙碌;result=0,不忙
***************************************************/
unsigned char BusyTest(void)
{
bit result;
RS=0; //根據規定,RS為低電平,RW為高電平時,可以讀狀態
RW=1;
E=1; //E=1,才允許讀寫
_nop_(); //空操作
_nop_();
_nop_();
_nop_(); //空操作四個機器周期,給硬件反應時間
result=BF; //將忙碌標志電平賦給result
E=0;
return result;
}
/*****************************************************
函數功能:將模式設置指令或顯示地址寫入液晶模塊
入口參數:dictate
***************************************************/
void WriteInstruction (unsigned char dictate)
{
flag1=0;flag2=0;flag3=0;flag4=0;
// while(BusyTest()==1); //如果忙就等待
RS=0; //根據規定,RS和R/W同時為低電平時,可以寫入指令
RW=0;
E=0; //E置低電平(根據表8-6,寫指令時,E為高脈沖,
// 就是讓E從0到1發生正跳變,所以應先置"0"
_nop_();
_nop_(); //空操作兩個機器周期,給硬件反應時間
if((dictate & 0x10 )){
flag1=1; }else
{flag1=0;}
if((dictate & 0x20 )){
flag2=1; }else
{flag2=0;}
if((dictate & 0x40 )){
flag3=1; }else
{flag3=0;}
if((dictate & 0x80 )){
flag4=1; }else
{flag4=0;}
tx=0; //可以執行下步
delay(30);
if(flag1==1&&flag2==1&&flag3==1&&flag4==1) {PrintString1("L111100000");}
else if(flag1==0&&flag2==1&&flag3==1&&flag4==1) {PrintString1("L011100000");}
else if(flag1==1&&flag2==0&&flag3==1&&flag4==1) {PrintString1("L101100000");}
else if(flag1==0&&flag2==0&&flag3==1&&flag4==1) {PrintString1("L001100000");}
else if(flag1==1&&flag2==1&&flag3==0&&flag4==1) {PrintString1("L110100000");}
else if(flag1==0&&flag2==1&&flag3==0&&flag4==1) {PrintString1("L010100000");}
else if(flag1==1&&flag2==0&&flag3==0&&flag4==1) {PrintString1("L100100000");}
else if(flag1==0&&flag2==0&&flag3==0&&flag4==1) {PrintString1("L000100000");}
else if(flag1==1&&flag2==1&&flag3==1&&flag4==0) {PrintString1("L111000000");}
else if(flag1==0&&flag2==1&&flag3==1&&flag4==0) {PrintString1("L011000000");}
else if(flag1==1&&flag2==0&&flag3==1&&flag4==0) {PrintString1("L101000000");}
else if(flag1==0&&flag2==0&&flag3==1&&flag4==0) {PrintString1("L001000000");}
else if(flag1==1&&flag2==1&&flag3==0&&flag4==0) {PrintString1("L110000000");}
else if(flag1==0&&flag2==1&&flag3==0&&flag4==0) {PrintString1("L010000000");}
else if(flag1==1&&flag2==0&&flag3==0&&flag4==0) {PrintString1("L100000000");}
else if(flag1==0&&flag2==0&&flag3==0&&flag4==0) {PrintString1("L000000000");}
delay(30); //等待從機將信號置零
tx=1;
while(rx==1); //如果從機已執行完
if((dictate & 0x01 )){
p00=1; }else
{p00=0;}
if((dictate & 0x02 )){
p01=1; }else
{p01=0;}
if((dictate & 0x04 )){
p02=1; }else
{p02=0;}
if((dictate & 0x08 )){
p03=1; }else
{p03=0;}
_nop_();
_nop_();
_nop_();
_nop_(); //空操作四個機器周期,給硬件反應時間
E=1; //E置高電平
_nop_();
_nop_();
_nop_();
_nop_(); //空操作四個機器周期,給硬件反應時間
E=0; //當E由高電平跳變成低電平時,液晶模塊開始執行命令
}
/*****************************************************
函數功能:指定字符顯示的實際地址
入口參數:x
***************************************************/
void WriteAddress(unsigned char x)
{
WriteInstruction(x|0x80); //顯示位置的確定方法規定為"80H+地址碼x"
}
/*****************************************************
函數功能:將數據(字符的標準ASCII碼)寫入液晶模塊
入口參數:y(為字符常量)
***************************************************/
void WriteData(unsigned char y)
{
flag1=0;flag2=0;flag3=0;flag4=0;
// while(BusyTest()==1);
RS=1; //RS為高電平,RW為低電平時,可以寫入數據
RW=0;
E=0; //E置低電平(根據表8-6,寫指令時,E為高脈沖,
// 就是讓E從0到1發生正跳變,所以應先置"0"
if(y & 0x10 ){
flag1=1; }else
{flag1=0;}
if(y & 0x20 ){
flag2=1; }else
{flag2=0;}
if(y & 0x40 ){
flag3=1; }else
{flag3=0;}
if(y & 0x80 ){
flag4=1; }else
{flag4=0;}
tx=0; //可以執行下步
delay(30);
if(flag1==1&&flag2==1&&flag3==1&&flag4==1) {PrintString1("L111100000");}
else if(flag1==1&&flag2==1&&flag3==1&&flag4==0) {PrintString1("L111000000");}
else if(flag1==1&&flag2==1&&flag3==0&&flag4==1) {PrintString1("L110100000");}
else if(flag1==1&&flag2==1&&flag3==0&&flag4==0) {PrintString1("L110000000");}
else if(flag1==1&&flag2==0&&flag3==1&&flag4==1) {PrintString1("L101100000");}
else if(flag1==1&&flag2==0&&flag3==1&&flag4==0) {PrintString1("L101000000");}
else if(flag1==1&&flag2==0&&flag3==0&&flag4==1) {PrintString1("L100100000");}
else if(flag1==1&&flag2==0&&flag3==0&&flag4==0) {PrintString1("L100000000");}
else if(flag1==0&&flag2==1&&flag3==1&&flag4==1) {PrintString1("L011100000");}
else if(flag1==0&&flag2==1&&flag3==1&&flag4==0) {PrintString1("L011000000");}
else if(flag1==0&&flag2==1&&flag3==0&&flag4==1) {PrintString1("L010100000");}
else if(flag1==0&&flag2==1&&flag3==0&&flag4==0) {PrintString1("L010000000");}
else if(flag1==0&&flag2==0&&flag3==1&&flag4==1) {PrintString1("L001100000");}
else if(flag1==0&&flag2==0&&flag3==1&&flag4==0) {PrintString1("L001000000");}
else if(flag1==0&&flag2==0&&flag3==0&&flag4==1) {PrintString1("L000100000");}
else if(flag1==0&&flag2==0&&flag3==0&&flag4==0) {PrintString1("L000000000");}
delay(30);
tx=1;
while(rx==1);
if((y & 0x01 )){
p00=1; }else
{p00=0;}
if((y & 0x02 )){
p01=1; }else
{p01=0;}
if((y & 0x04 )){
p02=1; }else
{p02=0;}
if((y & 0x08 )){
p03=1; }else
{p03=0;}
_nop_();
_nop_();
_nop_();
_nop_(); //空操作四個機器周期,給硬件反應時間
E=1; //E置高電平
_nop_();
_nop_();
_nop_();
_nop_(); //空操作四個機器周期,給硬件反應時間
E=0; //當E由高電平跳變成低電平時,液晶模塊開始執行命令
}
/*****************************************************
函數功能:對LCD的顯示模式進行初始化設置
***************************************************/
void InitLCD1602(void)
{
delay(200); //延時15ms,首次寫指令時應給LCD一段較長的反應時間
WriteInstruction(0x38); //0x38
delay(200);
WriteInstruction(0x0c);
delay(200);
WriteInstruction(0x04);
delay(200);
WriteInstruction(0x01); //清屏幕指令,將以前的顯示內容清除
delay(200);
}
/**********************************************************/
void main(void)
{
unsigned char i,j,adc_i,adc_result[5],core2_adc[5],core_adc_i=1,core_adc_lcd1602=0;
unsigned int adc_j;
unsigned char y=0;
unsigned char core2_i;
/*******PWM***************/
unsigned char pwm1,pwm0;
unsigned int pwm_i;
/*******ADC配置***********/
double adc;
P1ASF = 0XE3;//0xff;
ADC_CONTR = ADC_360T | ADC_ON;//只選擇p10 若是所以選ADC_ON;
/********************PWM配置*****************************/
pwm0 = 0; // PWM0 初始值
pwm1 = 0; // PWM1 初始值
CCAP0H = pwm0; //set PWM wide
CCAPM0 = 0x42; //0x42 Setup PCA module 0 in PWM mode
CCAP1H = pwm1; //set PWM wide
CCAPM1 = 0x42; //0x42 Setup PCA module 1 in PWM mode
CMOD = (PCA_IDLE_DISABLE << 7) | (PCA_SOURCE_SELECT << 1); //初始化PCA模式寄存器。
CL = 0x00; //clear PCA counter
CH = 0x00;
CR = 1; //Start PCA counter
/********************************************************/
uart1_init();
uart2_init();
InitLCD1602();//調用LCD初始化函數
// AUXR |= 0x01; //串口1使用獨立波特率發生器, 波特率跟串口2一樣
// AUXR1 |= (1<<4); //將UART2從P1口切換到 RXD2--P1.2切換到P4.2 TXD2---P1.3切換到P4.3
WriteInstruction(0x01);//清顯示:清屏幕指令
WriteAddress(0x00); //設置顯示位置為第一行的第0個字
for(i=0;i<16;i++){
WriteData(string[ i]);
}
WriteAddress(0xc0); //設置顯示位置為第二行的第0個字
for(j=0;j<16;j++){
WriteData(string2[j]);
}
while(1){
/*
if(uart2_rd != uart2_wr) //串口2轉發
{
UART2_TxByte(RX2_Buffer[uart2_rd]);
if(++uart2_rd >= BUF_LENTH) uart2_rd = 0;
}
*/
//PWM
//for(pwm_i=0; pwm_i<3000; pwm_i++); //延時一下
pwm0+=20;
pwm1++;
CCAP0H = pwm0; //set PWM wide
CCAP1H = pwm1; //set PWM wide
//ADC
//for(adc_i=0; adc_i<8; adc_i++){ //8路ADC
adc_j = adc10_start(0/*adc_i*/);
adc=(double)adc_j/2.048;
adc_result[0]=(int)adc/1000 + '0';
adc_result[1]=(int)adc%1000/100 + '0';
adc_result[2]='.';
adc_result[3]=(int)adc%100/10 + '0';
adc_result[4]=(int)adc%10 + '0';
//}
//LCD1602
WriteAddress(0x07); //設置顯示位置為第一行的第0個字
for(i=0;i<5;i++){
WriteData((char)adc_result[ i]);
}
WriteAddress(0xc7); //設置顯示位置為第二行的第0個字
if(uart1_rd !=6/* uart1_wr*/&&RX1_Buffer[0]=='A'){ //串口0轉發
for(core_adc_i=1,core_adc_lcd1602=0;core_adc_i<6,core_adc_lcd1602<5;core_adc_i++,core_adc_lcd1602++){
core2_adc[core_adc_lcd1602]=RX1_Buffer[core_adc_i];
}
}
for(core2_i=0;core2_i<5;core2_i++){
WriteData((char)core2_adc[core2_i]);//此處數據接收無問題
//UART2_TxByte((char)core2_adc[core2_i]);
if(++uart1_rd >= BUF_LENTH) uart1_rd = 0;
}
WriteInstruction(0x38); //0x38
}
}
void UART1_TxByte(unsigned char dat)
{
B_TI = 0;
SBUF = dat;
while(!B_TI);
B_TI = 0;
}
void UART2_TxByte(unsigned char dat)
{
B_TI2 = 0;
S2BUF = dat;
while(!B_TI2);
B_TI2 = 0;
}
void PrintString1(unsigned char *puts) //發送一串字符串
{
for (; *puts != 0; puts++) UART1_TxByte(*puts); //遇到停止符0結束
}
void PrintString2(unsigned char *puts) //發送一串字符串
{
for (; *puts != 0; puts++) UART2_TxByte(*puts); //遇到停止符0結束
}
void uart1_init(void)
{
PCON |= 0x80; //UART0 Double Rate Enable
SCON = 0x50; //UART0 set as 10bit , UART0 RX enable
TMOD &= ~(1<<6); //Timer1 Set as Timer, 12T
TMOD = (TMOD & ~0x30) | 0x20; //Timer1 set as 8 bits auto relaod
TH1 = T1_TimerReload; //Load the timer
TR1 = 1;
ES = 1;
EA = 1;
}
/**********************************************/
void UART0_RCV (void) interrupt 4
{
if(RI)
{
RI = 0;
RX1_Buffer[uart1_wr] = SBUF;
if(++uart1_wr >= BUF_LENTH) uart1_wr = 0;
}
if(TI)
{
TI = 0;
B_TI = 1;
}
}
/**********************************************/
void uart2_init(void)
{
AUXR |= (1 << 3); //串口2波特率加倍
S2CON = (S2CON & 0x3f) | (1<<6); //串口2模式1,8位UART,(2^S2SMOD / 32) * BRT溢出率
S2CON |= 1 << 4; //允許串2接收
AUXR |= 1 << 4; //baudrate use BRT
BRT = BRT_Reload;
IE2 |= 1; //允許串口2中斷
}
/**********************************************/
void UART2_RCV (void) interrupt 8
{
if(RI2)
{
CLR_RI2();
RX2_Buffer[uart2_wr] = S2BUF;
if(++uart2_wr >= BUF_LENTH) uart2_wr = 0;
}
if(TI2)
{
CLR_TI2();
B_TI2 = 1;
}
}
/*********************做一次ADC轉換 *******************/
unsigned int adc10_start(unsigned char channel) //channel = 0~7
{
unsigned int adc;
unsigned char i;
ADC_RES = 0;
ADC_RESL = 0;
ADC_CONTR = (ADC_CONTR & 0xe0) | ADC_START | channel;
i = 150;
do{
if(ADC_CONTR & ADC_FLAG)
{
ADC_CONTR &= ~ADC_FLAG;
adc = (unsigned int)ADC_RES;
adc = (adc << 2) | (ADC_RESL & 3);
return adc;
}
}while(--i); //超時檢測
return 1024;
}
從
/*************** 用戶定義參數 *****************************/
#define MAIN_Fosc 22118400L //define main clock
#define Baudrate1 9600 //define the baudrate, 如果使用BRT做波特率發生器,則波特率跟串口2一樣
//12T mode: 600~115200 for 22.1184MHZ, 300~57600 for 11.0592MHZ
#define Baudrate2 9600 //define the baudrate2,
//12T mode: 600~115200 for 22.1184MHZ, 300~57600 for 11.0592MHZ
#define BUF_LENTH 10 //定義串口接收緩沖長度
/**********************************************************/
#include <reg51.h>
sfr AUXR1 = 0xA2;
sfr AUXR = 0x8E;
sfr S2CON = 0x9A; //12C5A60S2雙串口系列
sfr S2BUF = 0x9B; //12C5A60S2雙串口系列
sfr IE2 = 0xAF; //STC12C5A60S2系列
sfr BRT = 0x9C;
unsigned char uart1_wr=0; //寫指針
unsigned char uart1_rd=0; //讀指針
unsigned char xdata RX1_Buffer[BUF_LENTH];
bit B_TI;
unsigned char uart2_wr=0; //寫指針
unsigned char uart2_rd=0; //讀指針
unsigned char xdata RX2_Buffer[BUF_LENTH];
bit B_TI2;
sbit p00=P0^0;
sbit p01=P0^1;
sbit p02=P0^2;
sbit p03=P0^3;
sbit tx=P2^0; //從機狀態線
sbit rx=P2^1; //從機狀態線
/****************** 編譯器自動生成,用戶請勿修改 ************************************/
#define T1_TimerReload (256 - MAIN_Fosc / 192 / Baudrate1) //Calculate the timer1 reload value at 12T mode
#define BRT_Reload (256 - MAIN_Fosc / 12 / 16 / Baudrate2) //Calculate BRT reload value
#define TimeOut1 (28800 / (unsigned long)Baudrate1 + 2)
#define TimeOut2 (28800 / (unsigned long)Baudrate2 + 2)
#define TI2 (S2CON & 0x02) != 0
#define RI2 (S2CON & 0x01) != 0
#define CLR_TI2() S2CON &= ~0x02
#define CLR_RI2() S2CON &= ~0x01
/**********************************************************/
/*****************ADC配置*************************/
sfr P1ASF = 0x9D; //12C5A60AD/S2系列模擬輸入(AD或LVD)選擇
sfr ADC_CONTR = 0xBC; //帶AD系列
sfr ADC_RES = 0xBD; //帶AD系列
sfr ADC_RESL = 0xBE; //帶AD系列
// 7 6 5 4 3 2 1 0 Reset Value
//sfr ADC_CONTR = 0xBC; ADC_POWER SPEED1 SPEED0 ADC_FLAG ADC_START CHS2 CHS1 CHS0 0000,0000 //AD 轉換控制寄存器
#define ADC_OFF() ADC_CONTR = 0
#define ADC_ON (1 << 7)
#define ADC_90T (3 << 5)
#define ADC_180T (2 << 5)
#define ADC_360T (1 << 5)
#define ADC_540T 0
#define ADC_FLAG (1 << 4) //軟件清0
#define ADC_START (1 << 3) //自動清0
#define ADC_CH0 0
#define ADC_CH1 1
#define ADC_CH2 2
#define ADC_CH3 3
#define ADC_CH4 4
#define ADC_CH5 5
#define ADC_CH6 6
#define ADC_CH7 7
unsigned int adc10_start(unsigned char channel); //channel = 0~7
double adc;
/********************PWM******************************/
#define PCA_IDLE_DISABLE 0 //1: MCU在IDLE模式時禁止PCA工作。 0: MCU在IDLE模式時允許PCA工作。
#define PCA_SOURCE_SELECT 4 //選擇PCA的基準時鐘源。
//0:系統時鐘Fosc/12。
//1:系統時鐘Fosc/2。
//2:定時器0的溢出。
//3:ECI/P3.4腳的外部時鐘輸入(最大=Fosc/2)。
//4:系統時鐘Fosc。
//5:系統時鐘Fosc/4。
//6:系統時鐘Fosc/6。
//7:系統時鐘Fosc/8。
sfr CCON = 0xD8;
sfr CMOD = 0xD9;
//sfr CCAPM0 = 0xDA; //PCA module 0 work mode
sfr CCAPM1 = 0xDB; //PCA module 1 work mode
sfr CL = 0xE9; //PCA counter
//sfr CCAP0L = 0xEA; //PCA模塊0的捕捉/比較寄存器低8位。
sfr CCAP1L = 0xEB; //PCA模塊1的捕捉/比較寄存器低8位。
//sfr PCA_PWM0 = 0xF2; //PCA模塊0 PWM寄存器。
sfr PCA_PWM1 = 0xF3; //PCA模塊1 PWM寄存器。
sfr CH = 0xF9;
//sfr CCAP0H = 0xFA; //PCA模塊0的捕捉/比較寄存器高8位。
sfr CCAP1H = 0xFB; //PCA模塊1的捕捉/比較寄存器高8位。
//sbit CCF0 = CCON^0; //PCA 模塊0中斷標志,由硬件置位,必須由軟件清0。
sbit CCF1 = CCON^1; //PCA 模塊1中斷標志,由硬件置位,必須由軟件清0。
sbit CR = CCON^6; //1: 允許PCA計數器計數,必須由軟件清0。
sbit CF = CCON^7; //PCA計數器溢出(CH,CL由FFFFH變為0000H)標志。PCA計數器溢出后由硬件置位,必須由軟件清0。
//#define PWM0_NORMAL() PCA_PWM0 = 0 //PWM0正常輸出(默認)
//#define PWM0_OUT_0() PCA_PWM0 = 3 //PWM0一直輸出0
#define PWM1_NORMAL() PCA_PWM1 = 0 //PWM1正常輸出(默認)
#define PWM1_OUT_0() PCA_PWM1 = 3 //PWM1一直輸出0
/******************** 本地函數聲明 ***************/
void uart1_init(void);
void uart2_init(void);
void UART1_TxByte(unsigned char dat);
void UART2_TxByte(unsigned char dat);
void PrintString1(unsigned char *puts);
void PrintString2(unsigned char *puts);
unsigned int adc10_start(unsigned char channel);
void main(void)
{
unsigned char adc_i,adc_result[6],adc_s;
unsigned int adc_j;
/*******PWM***************/
unsigned char pwm1,pwm0;
unsigned int pwm_i;
/*******ADC配置***********/
double adc;
P1ASF = 0XE7;//0xff;
ADC_CONTR = ADC_360T | ADC_ON;//只選擇p10 若是所以選ADC_ON;
/********************PWM配置*****************************/
//pwm0 = 0; // PWM0 初始值
pwm1 = 0; // PWM1 初始值
//CCAP0H = pwm0; //set PWM wide
//CCAPM0 = 0x42; //0x42 Setup PCA module 0 in PWM mode
CCAP1H = pwm1; //set PWM wide
CCAPM1 = 0x42; //0x42 Setup PCA module 1 in PWM mode
CMOD = (PCA_IDLE_DISABLE << 7) | (PCA_SOURCE_SELECT << 1); //初始化PCA模式寄存器。
CL = 0x00; //clear PCA counter
CH = 0x00;
CR = 1; //Start PCA counter
/********************************************************/
// AUXR |= 0x01; //串口1使用獨立波特率發生器, 波特率跟串口2一樣
// AUXR1 |= (1<<4); //將UART2從P1口切換到 RXD2--P1.2切換到P4.2 TXD2---P1.3切換到P4.3
uart1_init();
uart2_init();
while(1)
{
//PWM
pwm1+=2;
CCAP1H = pwm1; //set PWM wide
//ADC
//for(adc_i=0; adc_i<8; adc_i++){ //8路ADC
adc_j = adc10_start(0/*adc_i*/);
adc=(double)adc_j/2.048;
adc_result[0]='A';
adc_result[1]=(int)adc/1000 + '0';
adc_result[2]=(int)adc%1000/100 + '0';
adc_result[3]='.';
adc_result[4]=(int)adc%100/10 + '0';
adc_result[5]=(int)adc%10 + '0';
//}
for(adc_s=0;adc_s<6;adc_s++){
UART1_TxByte((char)adc_result[adc_s]);
}
if((uart1_rd != uart1_wr)&&RX1_Buffer[0]=='1') //串口0轉發
{
UART2_TxByte(RX1_Buffer[uart1_rd]);
if(++uart1_rd >= BUF_LENTH) uart1_rd = 0;
}else if((uart1_rd !=10 /*uart1_wr*/)&&RX1_Buffer[0]=='L'&&tx==0) //串口0轉發
{
rx=1; //從機開始執行,主機等待
if(RX1_Buffer[1]=='1'){
p00=1;}else {p00=0;}
if(RX1_Buffer[2]=='1'){
p01=1;}else {p01=0;}
if(RX1_Buffer[3]=='1'){
p02=1;}else {p02=0;}
if(RX1_Buffer[4]=='1'){
p03=1; }else {p03=0;}
UART2_TxByte(RX1_Buffer[uart1_rd]);
if(++uart1_rd >= BUF_LENTH) uart1_rd = 0;
rx=0; //從機已執行完
}
if(uart2_rd != uart2_wr) //串口2轉發
{
//UART1_TxByte(RX2_Buffer[uart2_rd]);
if(++uart2_rd >= BUF_LENTH) uart2_rd = 0;
}
}
}
void UART1_TxByte(unsigned char dat)
{
B_TI = 0;
SBUF = dat;
while(!B_TI);
B_TI = 0;
}
void UART2_TxByte(unsigned char dat)
{
B_TI2 = 0;
S2BUF = dat;
while(!B_TI2);
B_TI2 = 0;
}
void PrintString1(unsigned char *puts) //發送一串字符串
{
for (; *puts != 0; puts++) UART1_TxByte(*puts); //遇到停止符0結束
}
void PrintString2(unsigned char *puts) //發送一串字符串
{
for (; *puts != 0; puts++) UART2_TxByte(*puts); //遇到停止符0結束
}
void uart1_init(void)
{
PCON |= 0x80; //UART0 Double Rate Enable
SCON = 0x50; //UART0 set as 10bit , UART0 RX enable
TMOD &= ~(1<<6); //Timer1 Set as Timer, 12T
TMOD = (TMOD & ~0x30) | 0x20; //Timer1 set as 8 bits auto relaod
TH1 = T1_TimerReload; //Load the timer
TR1 = 1;
ES = 1;
EA = 1;
}
/**********************************************/
void UART0_RCV (void) interrupt 4
{
if(RI)
{
RI = 0;
RX1_Buffer[uart1_wr] = SBUF;
if(++uart1_wr >= BUF_LENTH) uart1_wr = 0;
}
if(TI)
{
TI = 0;
B_TI = 1;
}
}
/**********************************************/
void uart2_init(void)
{
AUXR |= (1 << 3); //串口2波特率加倍
S2CON = (S2CON & 0x3f) | (1<<6); //串口2模式1,8位UART,(2^S2SMOD / 32) * BRT溢出率
S2CON |= 1 << 4; //允許串2接收
AUXR |= 1 << 4; //baudrate use BRT
BRT = BRT_Reload;
IE2 |= 1; //允許串口2中斷
}
/**********************************************/
void UART2_RCV (void) interrupt 8
{
if(RI2)
{
CLR_RI2();
RX2_Buffer[uart2_wr] = S2BUF;
if(++uart2_wr >= BUF_LENTH) uart2_wr = 0;
}
if(TI2)
{
CLR_TI2();
B_TI2 = 1;
}
}
/*********************做一次ADC轉換 *******************/
unsigned int adc10_start(unsigned char channel) //channel = 0~7
{
unsigned int adc;
unsigned char i;
ADC_RES = 0;
ADC_RESL = 0;
ADC_CONTR = (ADC_CONTR & 0xe0) | ADC_START | channel;
i = 150;
do{
if(ADC_CONTR & ADC_FLAG)
{
ADC_CONTR &= ~ADC_FLAG;
adc = (unsigned int)ADC_RES;
adc = (adc << 2) | (ADC_RESL & 3);
return adc;
}
}while(--i); //超時檢測
return 1024;
}
|