這幾天用單片機做了一個東西,用到了adc,uart串口,模擬i2c(oled用)。adc用了兩個通道,uart用的串口1,就是下載程序用的P3.0和P3.1。模擬i2c中的scl用p3.6,sda用p3.7。我原來做了很多串口的東西,感覺串口已經不難了。我就先把 adc 和 i2c的oled12864 做好了,adc能正常轉換,oled也能顯示漢字。我最后加上了串口,結果發現反而是我覺得簡單的串口出了問題 
串口是這樣的,單片機串口發送一字節,電腦上的串口助手能收到,但是單片機發送完馬上自動復位,就是崩潰了。
我認為可能是這個單片機的串口出了問題,就重新往里燒寫了一個最簡單的串口通信程序,結果簡單的程序可以發送,就是說還是這個程序出了問題。
我又覺得是adc或i2c干擾了串口,于是把adc和i2c都關掉了,又換了引腳位置,結果還是不行。 
我為了測試,在程序的開頭發送一字節串口,因為出了問題,所以單片機在一直復位,導致oled不顯示,但是串口初始化不會崩潰,往sbuf里寫數就會出問題。而在發送之前的oled初始化能正常運行。
我現在根本不知道問題出在哪,這又是一個我認為最簡單的串口發送,所以我也找不到原因。
單片機用的stc15w4k32s4,有多串口,我只用了p3.0和p3.1。也不知道是不是這一點出了問題。
放上一部分代碼,oled沒問題。
void main()
{
uchar i,x,y;
ch=0x00;
IOMode00();
OLED_Init(0x20,0x00); //oled12864初始化,可以正常運行
InitADC(0x00,0x0C); //adc初始化,可以運行
serialinit(1,11059200,9600); //串口初始化
SBUF=0x20; //=========串口發送,有問題==========
while(!TI);
TI=0;
OLED16dot(0,2,0,xytab);
OLED16dot(0,4,1,xytab);
for(i=0;i<5;i++)
{
OLED16dot(16+i*16,0,i,titletab);
}
for(i=0;i<5;i++)
{
OLED16dot(16+i*16,6,i,keytab);
}
//OLED816dot(16,2,4,numbertab);
//OLED816dot(16,4,5,numbertab);
while(1){
Delay30ms();
x=GetADC(2);
y=GetADC(3);
dispnum(x,2);
dispnum(y,4);
if (P14){
OLED16dot(48,6,2,keytab);
ch&=0x0F;}
else {
OLED16dot(48,6,5,keytab);
ch|=0x10;}
selectxy(x,y);
}
}
關于oled的放上來其實都沒有什么用。
放一下串口和adc
void serialinit(int port,ULONG32 FOSC,UINT16 BAUD) //參數:串口號,晶振頻率(頻率乘1000000=10^6),波特率
//(最高波特率65535,串口助手65535之內最高可選57600)
{
switch(port)
{
case 2:
P_SW1 &= 0x7F; //將P_SW1前兩位設置成01 (P3.6/RxD_2, P3.7/TxD_2)
break;
case 3:
P_SW1 &= 0xBF; //將P_SW1前兩位設置成10 (P1.6/RxD_3, P1.7/TxD_3)
break;
case 1:
default:
P_SW1 &= 0x3F; //將P_SW1前兩位設置成00 (P3.0/RxD, P3.1/TxD)
break;
}
SCON = 0x50; //8位可變波特率
T2L = (65536 - (FOSC/4/BAUD)); //設置波特率重裝值
T2H = (65536 - (FOSC/4/BAUD))>>8;
AUXR = 0x15; //T2為1T模式, 并啟動定時器2
//AUXR |= 0x01; //選擇定時器2為串口1的波特率發生器
ES = 1; //使能串口1中斷
EA = 1;
}
void sendbyte(UCHAR8 PrintByte)
{
//_push_(ACC);
//ACC = PrintByte; //獲取校驗位P (PSW.0)
while(!TI);
TI=0;
SBUF = PrintByte; //寫數據到UART數據寄存器
//_pop_(ACC);
}
串口初始化前面的switch都是判斷串口號的,只用到了串口1,不用看
adc程序:
//============初始化ADC============
void InitADC(uchar Speed,uchar kaiguan) //速度從低到高: 0x00 0x20 0x40 0x60
// 540個時鐘 360個時鐘 180個時鐘 90個時鐘
{
P1ASF = kaiguan; //設置P1口為AD口
ADC_RES = 0; //清除結果寄存器
//ADC_CONTR = ADC_POWER | ADC_SPEEDLL;
//CLK_DIV |= 0x20;
ADC_CONTR=0x80|Speed; //簡化上面一行
Delay1ms(); //ADC上電并延時
}
uchar GetADC(uchar ch)
{
//uint adcres = 0;
//ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ch | ADC_START;
//P1ASF = 0xff;
ADC_RES=0;
ADC_CONTR=0x88|ch; //簡化上面一行
_nop_(); //等待4個NOP
_nop_();
_nop_();
_nop_();
while (!(ADC_CONTR & 0x10));//等待ADC轉換完成
//ADC_CONTR &= ~ADC_FLAG; //Close ADC
ADC_CONTR=0x80;
//P1ASF = 0x00;
return ADC_RES; //返回ADC結果
}
adc只用了8位。
誰能幫我看看啊
|