嵌入式复习.docx
《嵌入式复习.docx》由会员分享,可在线阅读,更多相关《嵌入式复习.docx(14页珍藏版)》请在冰点文库上搜索。
![嵌入式复习.docx](https://file1.bingdoc.com/fileroot1/2023-5/7/bc4a2827-67c7-4050-b4ae-12886c0a28a5/bc4a2827-67c7-4050-b4ae-12886c0a28a51.gif)
嵌入式复习
Ch4
GPIO输出实验电路原理图
GPIO输出实验程序main.c
#include“config.h”
//定义LED控制口(输出高电平时点亮LED)
#defineLED1_CON(1<<11)/*GPE11口*/
#defineLED2_CON(1<<12)/*GPE12口*/
#defineLED3_CON(1<<4)/*GPH4口*/
#defineLED4_CON(1<<6)/*GPH6口*/
//定义蜂鸣器控制口
#defineBEEP(1<<10)/*GPH10口*/
#defineBEEP_MASK(~BEEP)
voidDelayNS(unit32dly)
{……}
/*控制蜂鸣器Be一声*/
voidRunBeep(void)
{rGPHDAT=rGPHDAT&BEEP_MASK;DelayNS(5);//BEEP=0
rGPHDAT=rGPHDAT|BEEP;DelayNS(5);//BEEP=1
}
voidLED_DispAllOn(void)
{
rGPHDAT=rGPHDAT|(0x03<<11);
rGPHDAT=rGPHDAT|(0x05<<4);
}
voidLED_DispAllOff(void)
{
rGPHDAT=rGPHDAT&(~(0x03<<11));
rGPHDAT=rGPHDAT&(~(0x05<<4));
}
voidLED_DispNum(unit32dat)
{//四只LED灯显示0000—1111十六进制数
dat=dat&0x0000000F;//参数过滤
//控制LED4、LED3显示(d3、d2位)
if(dat&0x08)
rGPHDAT=rGPHDAT|(0x01<<6);
else
rGPHDAT=rGPHDAT&(~(0x01<<6));
if(dat&0x04)
rGPHDAT=rGPHDAT|(0x01<<4);
else
rGPHDAT=rGPHDAT&(~(0x01<<4));
//控制LED2、LED1显示(d1、d0位)
rGPEDAT=(rGPEDAT&(~(0x03<<11)))|((dat&0x03)<<11);
}
intmain(void)
{inti;
//初始化I/O,rGPECON[25:
22]=0101b,GPE11、GPE12为输出
rGPECON=(rGPECON&(~(0x0F<<22)))|(0x05<<22);
//GPH4、GPH6为输出、GPH10为输出
rGPHCON=(rGPHCON&(~(0x33<<8)))|(0x11<<8);
rGPHCON=(rGPHCON&(~(0x03<<20)))|(0x05<<20);
while
(1)
{RunBeep();//蜂鸣器响一声for(i=0;i<5;i++)//LED全闪烁5次
{
LED_DisAllOff();//LED全熄灭DelayNS(5);LED_DisAllOn();//LED全点亮
DelayNS(5);
}
for(i=0;i<16;i++)//控制LED指示0~F的16进制数值
{LED_DisNum(i);//显示数值i
DelayNS(5);
}
}
return(0);
}
GPIO输入实验电路原理图
#include“config.h”
//定义独立按键KEY1的输入口
#defineKEY_CON(1<<4)/*GPF4口*/
//定义蜂鸣器控制口
#defineBEEP(1<<10)/*GPH10口*/
#defineBEEP_MASK(~BEEP)
intmain(void)
{//rGPFCON[9:
8]=00b,GPF4为GPIO输入模式
rGPFCON=(rGPFCON&(~(0x03<<8)));
//rGPHCON[21:
20]=01b,GPH10为GPIO输出模式
rGPHCON=(rGPHCON&(~(0x03<<20)))|(0x01<<20);
while
(1)
{if(rGPFDAT&KEY_CON)//读取GPF4是否为高电平
{
rGPHDAT=rGPHDAT|BEEP;//为高电平则GPH10=1
}
else
{
rGPHDAT=rGPHDAT&BEEP_MASK;//为低则GPH10=0
}
DelayNS
(1);
}
return(0);
}
Ch6
中断实验程序解析
独立按键KEY1电路原理如图所示,设置GPFCON寄存器来选择GPF4引脚为外部中断EINT4功能,此时通过按下KEY1键即可触发外部中断。
初始化S3C2410A中断控制器,设置EINT4为IRQ中断,并使能中断允许。
初始化完成后,等待外部中断产生。
中断服务程序里负责把LED1控制口输出信号取反,清除中断标志后退出中断。
#include“config.h”
//定义LED控制口(输出高电平时点亮LED)
#defineLED1_CON(1<<11)/*GPE11口*/
#defineLED2_CON(1<<12)/*GPE12口*/
#defineLED3_CON(1<<4)/*GPH4口*/
#defineLED4_CON(1<<6)/*GPH6口*/
//定义独立按键KEY1的输入口
#defineKEY_CON(1<<4)/*GPF4口*/
//定义LED1控制值变量
unit8ledcon=0x00
/**Eint4中断服务程序。
把LED1控制口输出信号取反.*/
voidIRQ_Eint4(void)
{
inti;
rGPFCON=rGPFCON&(~(0x03<<8));//设置GPIO输入
for(i=0;i<10000;i++);//延时去抖动
if(rGPFDAT&KEY_CON)//为真则是假按键,则直接退出
{
rGPFCON=rGPFCON|(0x02<<8);//设置GPIO为EINT4中断
rEINTPEND=(1<<4);//清除中断标志
rSRCPND=(1<<4);
rINTPND=rINTPND;
return;
}
rGPFCON=rGPFCON|(0x02<<8);//设置回EINT4中断口
if(ledcon)//把LED1控制口输出信号取反
{
ledcon=0;
rGPEDAT=rGPEDAT&(~LED1_CON);
}
else
{
ledcon=1;
rGPEDAT=rGPEDAT&|LED1_CON;
}
rEINTPEND=(1<<4);//清除中断标志,发生中断该位置1
rSRCPND=(1<<4);
rINTPND=rINTPND;//清除中断未决寄存器的方法
}
voidEINT_init(void)
{
//设置GPF4引脚为外部中断EINT4功能
rGPFCON=(rGPFCON&0xFFFFFCFF)|(0x02<<8);
//外部中断EINT4设置为下降沿触发
rEXTINT0=(0x2<<16);
VICVectAddr[4]=(uint32)IRQ_Eint4;//中断向量地址设置
rPRIORITY=0x00000000;//使用默认的固定的优先级
rINTMOD=0x00000000;//所有中断均为IRQ中断
rINTMSK=~0x0000010;//使能EINT4中断
rEINTMASK=~0x00000010;//使能外部中断
}
intmain(void)
{
//rGPECON[25:
22]=0101b,GPE11、GPE12为GPIO输出
rGPECON=(rGPECON&(~(0x0F<<22)))|(0x05<<22);
//rGPHCON[13:
8]=01xx01b,GPH4、GPH6为GPIO输出
rGPHCON=(rGPHCON&(~(0x33<<8)))|(0x11<<8);
LED_DisAllOff();//熄灭LED1—LED4
EINT_init();//外部中断初始化
IRQEnable();//使能IRQ中断(清零CPSR寄存器的I位)
while
(1);//等待外部中断
return(0);
}
Ch8
ADC实验内容
S3C2410A具有1个8通道的10位模数转换器(ADC),有采样保持功能,输入电压范围是0~3.3V,在2.5MHz的转换器时钟下,最大的转换速率可达500KSPS。
A/D转换器的AIN5、AIN7还可以与控制脚配合实现触摸屏输入功能。
为了正确使用A/D转换器,需要设置A/D转换器的时钟,还有A/D转换器的工作模式设置和输入通道选择,这都是通过ADCCON寄存器来设置的。
然后置位ADDCCON寄存器的ENABLE_START位来控制启动A/D转换,读ADCCON寄存器的ECFLG位来判断A/D转换是否已经结束。
当一次A/D转换结束后,通过读ADCDAT0寄存器来取得A/D转换结果,寄存器的低10位数据有效。
unit32ReadAdc(unit32ch)
{inti;
ch=ch&0x07;//参数过滤
//PRSCEN=1,使能分频器
//PRSCVL=(PCLK/ADC_FREQ1),即转换时钟为ADC_FREQ
//SEL_MUX=ch,设置ADC通道;STDBM=0,标准转换模式
//READ_START=0,禁止读(操作后)启动ADC
//ENABLE_START=0,不启动ADC
rADCCON=(1<<14)|((PCLK/ADC_FREQ1)<<6)|(ch<<3)|(0<<2)|(0<<1)|(0<<0);
rADCTSC=rADCTSC&(~0x03);//普通ADC模式(非触摸屏)
for(i=0;i<100;i++);
rADCCON=rADCCON|(1<<0);//启动ADC
while(rADCCON&0x01);//等待ADC启动
while(!
(rADCCON&0x8000));//等待ADC完成
return(rADCDAT0&0x3ff);//返回转换结果
}
intmain(void)
{intvin0,vin1;
UART_Select(0);//选择UART0
UART_Init();//初始化UART0
while
(1){
//进行A/D转换
adc0=ReadAdc(0);
adc1=ReadAdc
(1);
//通过串口输出显示
vin0=(adc0*3300)/1024;//读算实际电压值(mV)
vin1=(adc1*3300)/1024;
sprintf(disp_buf,“AIN0is%dmV,AIN1is%d\n”,vin0,vin1);
UART_SendStr(disp_buf);
DelayNS(20);
}
return(0);
}
Ch10
串口编程操作步骤
1、配置时钟,选择时钟源
2、配置ULCONn寄存器:
设置数据位、停止位校验位、模式
3、配置UCONn寄存器:
设置数据接收和发送模式、时钟源
3、设置UFCONn:
启用或禁止FIFO
4、配置UBRDIVn和UDIVSLOTn:
计算波特率
5、发送数据:
等待发送器为空,将要发送的8位数据赋给发送缓存寄存器UTXHn
6、接收数据:
等待接收缓冲区有数据可读,从接收缓存寄存器URXHn中取出数据。
波特率设置
UBRDIV0(16位)与UDIVSLOT0(16位)是与UCLK相关的寄存器,进一步决定了baudrate(波特率)的值(单位是bps),在有了PCLK_PSYS与目标波特率的情况下,怎么设置UBRDIV0与UDIVSLOT0呢?
中间变量DIV_VAL,这个中间变量与PCLK_PSYS、bps有这样的函数关系:
DIV_VAL=(PCLK_PSYS/(bps*16))-1
同时DIV_VAL与UBRDIV0与UDIVSLOT0也有这样的函数关系:
DIV_VAL=UBRDIV0+光棍数/16 (光棍数是指UDIVSLOT0这个16位数在二进制形式下,1的数目)
举例
PCLK_PSYS=66Mhz,假设波特率为115200bps,那么DIV_VAL=66000000/(115200*16)-1=34.81左右,对应过来就是UBRDIV0=34,光棍数=12.96约为13吧,
那么UDIVSLOT0=b0001111111111111=0x1fff了,数一数,是不是13根光棍呢?
又比如PCLK_PSYS=66.5Mhz,需要115200bps,则DIV_VAL=35.079左右,对应过来UBRDIV0=35,光棍数1.26左右,约为1,那么UDIVSLOT0=0x1。
补充:
S3C2410的UART实验
下图是一个RS-232接口电路。
电路中所采用的电平转换电路芯片为MAX3232,S3C2410芯片的UART0相关引脚(即:
TxD0、RxD0、nRTS0、nCTS0)经过MAX3232电平转换后连接到DB9型的插座上。
这样就可以使用S3C2410芯片内部的UART0部件来控制符合RS-232标准的串行通信。
初始化编程
voidUART_Init(void)
{//I/O口设置(GPH3,GPH2)
rGPHUP=rGPHUP|(0x03<<2);
rGPHCON=(rGPHCON&(~0x000000F0))|(0x000000A0);
//串口模式设置
rUFCON0=0x00;//禁止FIFO功能
rUMCON0=0x00;//AFC(流控制)禁能
rULCON0=0x03;//禁止IrDA,无奇偶校验,1位停止位,8位数据位
rUCON0=0x245;//使用PCLK来生成波特率,发送电平触发模式,
//接收中断为边沿模式,使能接受错误中断,正常工作模式,
//串口波特率设置
rUBRDIV0=(int)(PCLK/16.0/UART_BPS+0.5)-1;
}
发送程序
使用串口发送数据时,将待发送数据写入UTXH0寄存器,然后通过读取UTRSTAT0寄存器的值判断数据是否发送完成。
voidUART_SendByte(uint8data)
{inti;
while(!
(rUTRSTAT0&0x02));//等待发送为空
for(i=0;i<10;i++);
rUTXH0=data;//发送数据
}
接收程序
串口数据接收时,通过读取UTRSTAT0寄存器的值判断是否接收到数据,然后从URXH0寄存器中读取数据,。
intUART_GetKey(void)
{inti;
while(!
(rUTRSTAT0&0x01));//等待接收为满
for(i=0;i<10;i++);
return(rURXH0);//发送数据
}
main.c函数
#include“config.h”
//串口接收字符
uint8g_getch=0;
intmain(void)
{inti;
UART_Select(0);//选择UART0
UART_Init();//初始化UART0
for(i=0;i<10;i++)
{UART_SendStr(“HelloWorld!
\n”);}
while
(1)
{g_getch=UART_GetKey();//接收字符
if(g_getch==0x0D)//判断是否为回车键
{UART_SendByte(‘\r’);//发送换行符
UART_SendByte(‘\n’);
}
else
{UART_SendByte(g_getch);//发送接收到的字符}
}
return(0);
}
I2C程序
//第一步,确定从设备和初始化设置
I2C0.I2CDS0=0x90;//(先清pending操作)写从设备(LM75)地址
I2C0.I2CSTAT0=0xf0;//设置主设备为主传送模式、EnableRx/Tx等
I2C0.I2CCON0=0xef;//使能ACK信号、设置预分频、使能中断、清pendingflag等
while(!
(I2C0.I2CCON0&(1<<4)));//等待收到从设备应答后产生中断请求,可以继续
//第二步,写命令,指示从设备模式
I2C0.I2CDS0=mode;//此处mode=0x0,表示读传感器数据模式
I2C0.I2CCON0=0xef;//设置和清pendingflag
while(!
(I2C0.I2CCON0&(1<<4)));
for(delay=0;delay<0x1fffff;delay++);}
//第三步,主设备读模式
I2C0.I2CDS0=0x90;
I2C0.I2CSTAT0=0xb0;//设置主机接收模式
I2C0.I2CCON0=0xef;
while(!
(I2C0.I2CCON0&(1<<4)));
I2C0.I2CCON0=0xef;//使能ACK信号,预分频512,使能中断Rx/Tx
for(delay=0;delay<0xffff;delay++);
high=I2C0.I2CDS0;//从LM75芯片获取温度数据(整数部分)
I2C0.I2CCON0=0x2f;//关闭ACK信号,预分频:
16,使能中断Rx/Tx
for(delay=0;delay<0xffff;delay++);
low=I2C0.I2CDS0;//从LM75芯片获取温度数据(小数部分)
I2C0.I2CSTAT0=0x90;//这两步是主机接收模式操作结束时的标准操作
I2C0.I2CCON0=0xef;//clearpendingflag