这几天用单片机做了一个东西,用到了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位。
谁能帮我看看啊
|