您尚未登录。

#1 Re: RISC-V » 基于MINI-C的应广单片机编程测试代码 » 2022-10-07 15:29:16

不知道放什么板块。只好放到RISC-V里了。

#2 RISC-V » 基于MINI-C的应广单片机编程测试代码 » 2022-10-07 15:28:29

缥缈九哥
回复: 1

玩一玩几毛钱的PADAUK应广单片机跃龙PFC161。缥缈九哥借鉴网上代码测试。
包含一个1MS定时器与1个PA6输入按键反转PA4输出,以及PA5的2MS脉冲波,PA3的1秒反转信号。详细见代码:

#include    "extern.h"
//================================================================================
.ramadr     0
word        gw_Point;
.ramadr        system
word        gw_T16Cnt;   
word        gw_Cnt;
byte         gb_Flag;
bit            b_T16_1ms        :    gb_Flag.0    //1MS
bit            b_1S_F            :    gb_Flag.1    //1S
byte        gb_KeyDebounce;
byte        gb_KeyNew;
byte        gb_KeyOld;
byte         gb_KeyValue;   
//------------------------------------------------------------
//LED            equ    PA.3               // 设置PA3为LED输出
//PON            equ    PA.4               // 设置PA4为电源控制
//PWM            equ    PA.5               // 设置PA5为PWM输出
//KEY            equ    PA.6               // 设置PA6为按钮控制
D_KEYPORT    equ    0b_0100_0000    // PA6 按键
D_KEY1        equ    0b_0100_0000    // PA6 按键
D_KeyBounce    equ    30*1000/1024    // 30ms
//================================================================================
void Test_DirectScanKey(void)
{
    if(b_T16_1ms)
    {
        b_T16_1ms = 0;
        a = pa & D_KEYPORT;
        a ^= D_KEYPORT;
        if(gb_KeyNew == a)
        {//读到值相同值,Debouce
            if(--gb_KeyDebounce == 0)
            {//Debounce结束
                if(gb_KeyOld != gb_KeyNew)
                {
                    gb_KeyValue = gb_KeyNew;
                    gb_KeyOld = gb_KeyNew;
                }
            }
        }
        else
        {
            gb_KeyNew = a;
            gb_KeyDebounce = D_KeyBounce;
        }
    }
}
//================================================================================
void Test_KeyProcess(void)
{
    //处理Key1
    if(gb_KeyValue == D_KEY1)
    {
        gb_KeyValue = 0;
        //pa4 电平翻转
        a = pa;a ^= 0x10;pa = a;
    }
}
//================================================================================
void FPPA0(void)
{
    .ADJUST_IC    SYSCLK=IHRC/4, IHRC=16MHz, VDD=5V;
    clkmd.En_WatchDog    =    1;        // WatchDog Enable
    //    Insert Initial Code
    //注:无PA.1,PA.2脚位
    //未使用端口需有防漏电设置,如加内部上拉
    PAPH    =    0b0100_0000;    //上拉控制寄存器,控制上拉高相应的引脚(1:启用,0:停用
    PAPL    =    0b0000_0000;    //下拉控制寄存器,控制下拉高相应的引脚(1:启用,0:停用)
    PAC        =    0b1011_1001;    //数据控制寄存器(1:输出模式,0:输入模式)
    PA        =    0b0000_0000;    //数据寄存器
    .delay 4000;
//------------------------------------------------------------
    //清除RAM
    gw_Point       =   _SYS(RAM_SIZE) - 1;
    a           =   0;
    do
    {
        *gw_Point  =   a;
    } while (--gw_Point$0);
//------------------------------------------------------------
    //初始化定时器 定时1MS
    gw_Point = 1024 - 1000;           
    stt16 gw_T16Cnt;
    $ t16m SYSCLK,/4,bit10;

    intrq     = 0;
    inten.2 = 1;
    engint;
//------------------------------------------------------------   
    while (1)
    {
//        ...   
        if(b_1S_F)
        {
            b_1S_F = 0;
            //PA3 反转
            a = pa;    a ^= 0x08;pa = a;
        }
        Test_DirectScanKey();
        Test_KeyProcess();
        .wdreset;
    }
}
//================================================================================
void    Interrupt (void)
{
    pushaf;
    if (Intrq.T16)
    {    //    T16 Trig
        //    User can add code
        Intrq.T16    =    0;
        //...
        stt16 gw_T16Cnt;

        //pa5 电平翻转
        a = pa;a ^= 0x20;pa = a;

        b_T16_1ms = 1;
        gw_Cnt++;
        if(gw_Cnt > 999)
        {//1S计数
            gw_Cnt = 0;
            b_1S_F = 1;
        }
    }
    popaf;
}
//缥缈九哥测试完毕!
//================================================================================
源码包:9G-LED.rar

#3 Cortex M0/M3/M4/M7 » 基于Keil.STM32H7xx_DFP.3.0.0整理的纯源码入门最小工程包 » 2022-03-08 16:11:12

缥缈九哥
回复: 1

听说STM32H7必须要用cubemx图形化HAL编程,要学一种新软件代码又不简洁,而另外一种基于MDKARM的RTM开发模式下各中依赖开发环境的源与PACK也不是很习惯,换了电脑换了开发平台可能因为丢失了头文件或者库编译不通过,或者版本不兼容痛苦。我觉得对于我这种传统STM32过来的老人习惯了直接全部工程中包含源代码比较合适。只好从代码中提取核心的API做了一个纯源码的工程包。
工程主要还是传统STM32一样,包含CMSIS头文件,启动S文件,系统初始化文件,CPU相关文件,驱动API相关的BSP包文件等。其余都是网上最新找到的库,API,初始化,头文件,其中主要还是一个个人应用入口的MAIN.C文件:

int main(void)
{
    int i=0;
    /* This project template calls firstly CPU_CACHE_Enable() function in order enable the CPU Cache.
     These functions are provided as template implementation that User may integrate in his application.
    */


    /* Configure the MPU attributes */
    MPU_Config();

    /* Enable the CPU Cache */
    CPU_CACHE_Enable();

    /* STM32H7xx HAL library initialization:
       - Configure the Systick to generate an interrupt each 1 msec
       - Set NVIC Group Priority to 4
       - Low Level Initialization
    */
    HAL_Init();

    /* Configure the system clock to 520 MHz */
    SystemClock_Config();

    /* Add your application code here */
    GPIO_LED_Init();
    UART3_init();

    printf("NUCLEO-H723ZG Build by yuanxihua@21cn.com on ("__DATE__" - "__TIME__ ")\n\r");
  /* Infinite loop */
    while (1)
    {   
        GPIO_LED_Test();
        printf("NUCLEO-H723ZG run %d \n\r",i++);
    }
}



直接上源代码:TEV8AE_code-20220308B.rar

#4 全志 SOC » 基于荔枝派nano的镜像烧录方法--缥缈九哥测试 » 2022-01-21 15:21:58

缥缈九哥
回复: 0

购买的板子是:
https://item.taobao.com/item.htm?spm=a1z09.2.0.0.70052e8d1HwnxK&id=584657396198    Sipeed lichee Nano 荔枝派 跨界开发板 多系统 Linux F1c100s   (焊接的SPIFLASH是新天下的XT25F128B)
烧录方法是本论坛的:sunxi-tools-win32support_f1c100s 里面的sunxi-fel.exe
登陆方法是:USB-TTL转换线直接接到 PE1 PE0 +5V GND 脚。PC登陆用的是SecureCRT 8.5 串口终端模式115200 8N1 无流控
镜像来源于:https://www.codenong.com/cs106854611/ (别的镜像不支持这个SPIFLASH,但是测试中文件系统莫名崩溃)
文件系统来源于:
https://whycan.com/t_2689.html   和 https://whycan.com/t_2688.html
烧录方法命令是:
(注意用本坛的zadig-2.3.exe安装WCID驱动,插USB线前短路SPIFLASH的1,2脚进入USB烧录模式,用sunxi-fel.exe命令行烧录)

D:\bin\sunxi-tools-win32support_f1c100s>sunxi-fel.exe -p spiflash-write 0 u-boot-sunxi-with-spl.bin
100% [================================================]   418 kB,   89.9 kB/s

D:\bin\sunxi-tools-win32support_f1c100s>sunxi-fel.exe -p spiflash-write 0x100000 suniv-f1c100s-licheepi-nano.dtb
100% [================================================]     8 kB,   32.5 kB/s

D:\bin\sunxi-tools-win32support_f1c100s>sunxi-fel.exe -p spiflash-write 0x110000 zImage
100% [================================================]  3656 kB,   96.3 kB/s

D:\bin\sunxi-tools-win32support_f1c100s>sunxi-fel.exe -p spiflash-write 0x510000  jffs2.bin
100% [================================================] 11469 kB,  101.6 kB/s

UBOOT启动命令行与参数是:
setenv bootcmd 'sf probe 0 50000000;sf read 0x80c00000 0x100000 0x4000;sf read 0x80008000 0x110000 0x400000;bootz 0x80008000 - 0x80c00000'
setenv bbotargs 'console=ttyS0,115200 root=/dev/mtdblock3 rootfstype=jffs2 mtdparts=spi0.0:1M(uboot),64K(dtb),4M(kernel),-(rootfs)'
saveenv
run bootcmd
两个不同的文件系统登陆命令是:

其中两个文件系统 :
jffs2.bin的登陆
opendeck login: root   
Password: whycan.cn
rootfs.jffs2的登陆
opendeck login: root
Password: opendeck

文件:sunxi-tools-win32support_f1c100-缥缈九哥测试整理.rar

#5 华芯微特 » 基于华芯微特SWM181CB的DS18B20温度传感器的1-wire驱动程序 » 2022-01-13 01:15:03

缥缈九哥
回复: 2

还是直接上代码吧:

/********************************************************************************
 * @file     ds18b20.c															*
 * @brief    The Driver code for DS18B20 with SWM181CBT6						*
 * @version  1.0.0																*
 * @date     2018/09/19 19:26:35												*
 *																				*
 * @note																		*
 * Copyright (C) 2000-2018 PM9GZY by yuanxihua@21cn.com. All rights reserved.	*
 ********************************************************************************/
/* Includes --------------------------------------------------------------------*/
#include "main.h"
/*
_________________________________________________
|	SWM181CBT6						DS18B20		|
|												|
|	DATA -	PC2			<--->		DQ0			|
|_______________________________________________|
*/
/* Private typedef -----------------------------------------------------------*/
#define SkipROM			0xCC		//跳过ROM 
#define SearchROM		0xF0		//搜索ROM 
#define ReadROM			0x33		//读ROM 
#define MatchROM		0x55		//匹配ROM 
#define AlarmROM		0xEC		//告警ROM 
 
#define StartConvert	0x44 		//开始温度转换,在温度转换期间总线上输出0,转换结束后输出1 
#define ReadScratchpad	0xBE 		//读寄存器的9个字节 
#define WriteScratchpad	0x4E 		//写寄存器的温度告警TH和TL 
#define CopyScratchpad	0x48 		//将寄存器的温度告警复制到EEPROM,在复制期间总线上输出0,复制完后输出1 
#define RecallEEPROM	0xB8  		//将EEPROM的温度告警复制到寄存器中,复制期间输出0,复制完成后输出1 
#define ReadPower		0xB4  		//读电源的供电方式:0为寄生电源供电;1为外部电源供电 
/* Private define ------------------------------------------------------------*/
#define PC2     				PIN2 
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
//void delay_us(uint32_t us)
//{
//    int32_t t=SysTick->VAL-(us*CyclesPerUs); 
//    if(t<0){t+=SysTick->LOAD;while((SysTick->CTRL&SysTick_CTRL_COUNTFLAG_Msk)==0){;}}
//    while(SysTick->VAL>t){;}
//}
//1.初始化
uint8_t DS18B20_init(uint32_t n)
{
	uint32_t i=0,ret=1;
	GPIO_Init(GPIOC, n, 1, 1, 0, 0);		//DQ 配置为输出引脚,开启上拉,推挽输出
	GPIO_SetBit(GPIOC, n);					//DQ=1;
	delay_us(900);							//稍作延时
	//开始初始化
	GPIO_ClrBit(GPIOC, n);					//DQ=0;
	delay_us(540);							//延时540us
	GPIO_SetBit(GPIOC, n);					//DQ=1;
	GPIO_Init(GPIOC, n, 0, 1, 0, 0);		//DQ 配置为输入引脚,开启上拉
	delay_us(60);							//稍作延时
	while(GPIO_GetBit(GPIOC, n))    		//等待DS18B20拉低总线
	{
		delay_us(1);				
        if(i++>240){ret=0;break;}			//初始化失败
	}
	GPIO_Init(GPIOC, n, 1, 1, 0, 0);		//DQ 配置为输出引脚,开启上拉,推挽输出
	GPIO_SetBit(GPIOC, n);					//DQ=1;
	delay_us(480);
	return ret;								//初始化成功
}
//2.写字节
void write_byte(uint32_t n,uint8_t dat)   	//写一个字节
{
	uint8_t i;
	for(i=0;i<8;i++)
	{
		GPIO_ClrBit(GPIOC, n);					//DQ=0; 总线拉低1us
		delay_us(1);	
		if(dat&0x01){GPIO_SetBit(GPIOC, n);}	//取最低位写入
		else{GPIO_ClrBit(GPIOC, n);}
		delay_us(60);				  			//延时60us
		GPIO_SetBit(GPIOC, n);					//DQ=1; 释放总线
		delay_us(1); 
		dat=dat>>1;    							//从低位开始写
	}
}
//3.读字节
uint8_t read_byte(uint32_t n)    				//读一个字节
{
	uint8_t i,dat=0;
	for(i=0;i<8;i++)
	{
		GPIO_ClrBit(GPIOC, n);					//DQ=0; 总线拉低1us
		delay_us(1);
		GPIO_SetBit(GPIOC, n);					//DQ=1; 释放总线
		GPIO_Init(GPIOC, n, 0, 1, 0, 0);		//DQ 配置为输入引脚,开启上拉
		delay_us(2);								//延时等待数据稳定 5
		dat=dat>>1;       						//从最低位开始读
		if(GPIO_GetBit(GPIOC, n)){dat|=0x80;}	//每次读一位
		else{dat&=0x7f;}
		delay_us(30); 							//等待读取数据稳定
		GPIO_Init(GPIOC, n, 1, 1, 0, 0);		//DQ 配置为输出引脚,开启上拉,推挽输出
		GPIO_SetBit(GPIOC, n);					//DQ=1; 释放总线
		delay_us(1); 
	}
	return dat;
}
//4.按位CRC运算
//Purpose:    To calculate an 8-bit CRC based on a polynomial and the series 
//            of data bytes 
//Note:       Polynomial used x^8 + x^5 + x^4 + 1 = 10001100 
//Inputs:     A pointer to an array of the data bytes and an uint8_t saying how many 
//            bytes there are in the data array 
//Outputs:    An uint8_t which is the calculated CRC 
uint8_t OneWireCRC8(uint8_t *buf, uint8_t len)
{
    #define CRC8_POLYNOMIAL 0x8C
    uint8_t crc=0,val=0,inb,mix;
    while(len--){inb=*buf++;if(inb){val=1;}for(uint8_t i=8;i;i--){mix=(crc^inb)&0x01;crc>>=1;if(mix){crc^=CRC8_POLYNOMIAL;}inb>>=1;}}
    if(!val){return 0xFF;}  /* If all bytes are 0, return a different CRC so that the test will fail */
    return crc;
}
//5.读温度
uint16_t read_temper(uint32_t n)
{    
	uint16_t temp=0xffff;uint8_t data[9],crc,ret;ret=ret; 
	ret=DS18B20_init(n);   
	write_byte(n,0xcc);	//跳过ROM操作命令
	write_byte(n,0x44);	//发送启动温度转换命令
	delay_us(2000);
	ret=DS18B20_init(n); 
	write_byte(n,0xcc);	//跳过ROM操作命令
	write_byte(n,0xbe);	//发送读温度寄存器命令
	delay_us(2000);
    
    for(int i=0;i<9;i++){data[i]=read_byte(n);}                         //read Scratchpad Memory of DS
    crc=OneWireCRC8(data,8);                                            //calculate crc
    if(crc==data[8]){temp=((uint16_t)data[1]<<8)|data[0];}              //compare : calculate with received
    return temp;        //返回温度值
}
//6.温度转换
float temper_change(uint32_t n)
{
    int32_t temper;float tp;
    temper=read_temper(n);
	printf("temper=0x%04x\n\r",temper);
    if(temper<0)    			//考虑负温度的情况
    {
        temper=temper-1;
        temper=~temper;
    }
    tp=temper/16;  		        //16位温度转换成10进制的温度
    temper=tp*100+0.5;   	    //留两个小数点,并四舍五入
	printf("DS18B20=%3.2f\n\r",tp);
    return temper;
}
//代码完毕

#6 Cortex M0/M3/M4/M7 » 基于华芯微特SWM181CB的ADXL357加速度计的SPI驱动程序 » 2022-01-13 01:08:30

缥缈九哥
回复: 0

直接上代码:

/********************************************************************************/
/* @file	adxl357.c															*/
/* @version	V1.00																*/
/* $author:	yuanxihua@21cn.com													*/
/* $Date: 	2022/01/13 02:54 $ 													*/
/* @brief 	SWM181CBT6 Series ADXL357 Driver Sample Code						*/
/*																				*/
/* @note																		*/
/* Copyright (C) 2010-2022 PM9GZY Technology Corp. All rights reserved.			*/
/*																				*/
/********************************************************************************/ 
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "adxl537.h"
/*
________________________________________________
|	SWM181CBT6						ADXL357		|
|												|
|	PA12	NSS0		---->		CS/SCL		|
|	PA13	MISO0		<----		MISO		|
|	PA14	MOSI0		---->		MOSI		|
|	PA15	SCLK0		---->		SCLK		|
|_______________________________________________|
*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define ADXL357_CS_L()		GPIO_ClrBit(GPIOA, PIN12)
#define ADXL357_CS_H()		GPIO_SetBit(GPIOA, PIN12)
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
void ADXL357_Initial(void);
void ADXL357_Reset(void);
/* Private functions ---------------------------------------------------------*/
void SPI0Init(void)
{
	SPI_InitStructure SPI_initStruct;

	GPIO_Init(GPIOA, PIN12, 1, 0, 0, 0);ADXL357_CS_H();					//GPIOC.4 -> IOSPI.SSEL
//	PORT_Init(PORTA, PIN12, PORTA_PIN12_SPI0_SSEL, 0);
	PORT_Init(PORTA, PIN13, PORTA_PIN13_SPI0_MISO, 1);
	PORT_Init(PORTA, PIN14, PORTA_PIN14_SPI0_MOSI, 0);
	PORT_Init(PORTA, PIN15, PORTA_PIN15_SPI0_SCLK, 0);
	
	SPI_initStruct.clkDiv = SPI_CLKDIV_4;	//80NS , 12500KHZ 
	SPI_initStruct.FrameFormat = SPI_FORMAT_SPI;
	SPI_initStruct.SampleEdge = SPI_SECOND_EDGE;
	SPI_initStruct.IdleLevel = SPI_HIGH_LEVEL;
	SPI_initStruct.WordSize = 8;
	SPI_initStruct.Master = 1;
	SPI_initStruct.RXHFullIEn = 0;
	SPI_initStruct.TXEmptyIEn = 0;
	SPI_initStruct.TXCompleteIEn = 0;
	SPI_Init(SPI0, &SPI_initStruct);
	SPI_Open(SPI0);
	
	ADXL357_Reset();
	ADXL357_Initial();
}
uint8_t ADXL357_Read(uint8_t addr,uint8_t *data,uint32_t len)
{
	uint8_t cmd=(addr<<1)|0x01;		// D0=R/W=1,读取模式
	ADXL357_CS_L();
	SPI_ReadWrite(SPI0,cmd);while(len--){*data++ =SPI_ReadWrite(SPI0,0x55)&0xff;}
	ADXL357_CS_H();
}
uint8_t ADXL357_Write(uint8_t addr,uint8_t *data,uint32_t len)
{
	uint8_t cmd=(addr<<1)&0xFE;		// D0=R/W=0,写入模式
	ADXL357_CS_L();
	SPI_ReadWrite(SPI0,cmd);while(len--){SPI_ReadWrite(SPI0,*data++);}
	ADXL357_CS_H();
}
uint8_t ADXL357_Read_Register(uint8_t addr){uint8_t val;ADXL357_Read(addr,&val,1);return val;}
void ADXL357_Write_Register(uint8_t addr,uint8_t data){ADXL357_Write(addr,&data,1);}
void ADXL357_Reset(void){ADXL357_Write_Register(ADXL357_Reset_REG,0x52);delay_ms(10);}
void ADXL357_Initial(void){}
float ADXL357_Read_TemperatureRead(void)
{
    uint8_t tmp[2];ADXL357_Read(ADXL357_TEMP2,tmp,2);uint16_t tempH=tmp[0]&0x0F,tempL=tmp[1];
	float Temperature = ((float)(tempH<<8)) + ((float)tempL);
	return (25-((Temperature-1885)/9.05));
}
	
void ADXL357_Test(void)
{
	uint8_t data[47];ADXL357_Read(ADXL357_DEVID_AD,data,sizeof(data));printf("\n\r");for(uint8_t i=0;i<sizeof(data);i++){printf("0x%02x ",data[i]);}printf("\n\r");
	printf("ADXL357_DEVID_AD  	= 0x%02x \n\r",ADXL357_Read_Register(ADXL357_DEVID_AD));
	printf("ADXL357_DEVID_MST 	= 0x%02x \n\r",ADXL357_Read_Register(ADXL357_DEVID_MST));
	printf("ADXL357_PARTID    	= 0x%02x \n\r",ADXL357_Read_Register(ADXL357_PARTID));
	printf("ADXL357_REVID     	= 0x%02x \n\r",ADXL357_Read_Register(ADXL357_REVID));	
	printf("ADXL357_Temperature	= %f \n\r",ADXL357_Read_TemperatureRead());
}

//代码完毕

#7 华芯微特 » 基于华芯微特SWM32SRE的IO模拟LIN总线-缥缈九哥 » 2021-12-15 18:04:11

缥缈九哥
回复: 0

基于华芯微特SWM32SRE的IO模拟LIN总线-缥缈九哥原创
不说其它的,上源代码吧:

#include "main.h"

/******************************************************************
Lin总线帧格式:帧头+应答

帧头:同步间隔段(至少13个显性电平)+同步间隔段间隔符(至少1位隐形电平)+同步段(0x55)+字节间间隔+PID(ID+校验位)
注:PID=ID(6位)+校验(2位)
ID 取值范围为: 0x00~0x3f
ID的取值分类:  
                信号携带帧 :                           0x00~0x3b
                诊断帧(主机请求):        0x3c
                诊断帧(从机应答):        0x3d
                保留帧 :                          0x3e,0x3f
P0 = ID0⊕ID1⊕ID2⊕ID4                异或运算
P1 = ┐(ID3⊕ID4⊕ID5⊕ID1)                异或后取非

应答:应答间隔+数据段+校验和段
注:数据段           低字节的低位先发
标准型校验和:        只校验数据段
增强型校验和:        校验数据段以及PID
诊断帧只能用标准型校验和

******************************************************************/

/******************************************************************
lin中断接收函数功能:
1、回环效果:即主机发送帧头或者主机发送帧头+应答,主机的中断服务程序都会接收数据。
        可以检测出:主机串口Tx、Rx、Lin脚,三个引脚上的信号是相同的(除了电平不同)。
2、当串口检测到连续至少11位显性电平即进入中断开始接收。
3、中断服务函数接收数据时按进程推进
        ①接收同步段是否OK?
        ②接收ID校验后解析是数据执行还是反馈
        若是执行:                                        若是反馈:
        ③分步接收数据                                ③准备数据在帧头结束后发送数据
        ④匹配校验数据是否正确
        ⑤解析数据并执行

******************************************************************/
uint8_t TxData = 0;
volatile uint32_t TBtIdx = 0;
volatile uint32_t TxBusy = 0;
#define UART_TX_PIN                        PIN18
#define UART_TX_LOW()                GPIO_ClrBit(GPION, UART_TX_PIN)
#define UART_TX_HIGH()                GPIO_SetBit(GPION, UART_TX_PIN)
#define UART_RX_PIN               PIN19
#define UART_RX_Value()                GPIO_GetBit(GPION, UART_RX_PIN)
//#define UART_RX_POINT                GPIOB, PIN7
#define UART_RX_POINT                GPION, PIN5
uint8_t RxData = 0;
volatile uint32_t RBtIdx = 0;
volatile uint32_t RxBusy = 0;

void uart1_putchar(uint8_t ch)
{
        while(TxBusy){;}                                                                //等待发送空闲
        TxData = ch;TBtIdx = 0;TxBusy = 1;
        TIMR_Start(TIMR1);
        while(TxBusy){;}                                                                //等待发送完成
}
void TIMR1_Handler(void)
{
        TIMR_INTClr(TIMR1);
        if(TBtIdx == 0){UART_TX_LOW(); }else                        //起始位
        if(TBtIdx <  9){if(TxData&0x1){UART_TX_HIGH();}else{UART_TX_LOW();}        TxData>>=1;}else
        if(TBtIdx == 9){UART_TX_HIGH();TIMR_Stop(TIMR1);TxBusy = 0;TBtIdx = 0;return;} //停止位
        TBtIdx++;
}
void uart1_putbuf(uint8_t *buf,uint32_t len){while(len--){uart1_putchar(*buf++);}}
void uart1_puts(char *str){while(*str){uart1_putchar((int)*str++);}}        

void UART1Init(void)
{
        GPIO_Init(GPION, PIN19, 0, 1, 0);                                //GPION.19 配置为输入引脚,开启上拉
        GPIO_Init(GPION, PIN18, 1, 0, 0);                                //GPION.18 配置为输出引脚,推挽输出
        GPIO_Init(GPION, PIN17, 1, 0, 0);                                //GPION.17 配置为输出引脚,推挽输出
        GPIO_Init(UART_RX_POINT , 1, 0, 0);                                //GPIOB.7  配置为输出引脚,推挽输出        用于调试接收采样点
        GPIO_SetBit(GPION, PIN18);
        GPIO_SetBit(GPION, PIN17);
        TIMR_Init(TIMR1, TIMR_MODE_TIMER, (SystemCoreClock/LIN_BPS)*1.00, 1);        //每1/LIN_BPS秒钟触发一次中断,用于发送
        TIMR_Init(TIMR2, TIMR_MODE_TIMER, (SystemCoreClock/LIN_BPS)*0.99, 1);        //每1/LIN_BPS秒钟触发一次中断,用于接收
}

// 主机帧头部分
// 起先是同步间隔段,因为作为主机要连续发送至少13位显性电平,这里用的是STM32自带的库函数,直接调用就行。
void Lin_SendBreak(void)
{
        UART_TX_LOW();                                                                        //显性电平
        DelayUs((1000000*13)/LIN_BPS);                                        //至少13位显性电平
        UART_TX_HIGH();                                                                        //隐形电平
        DelayUs((1000000*1 )/LIN_BPS);                                        //至少01位隐形电平
}

// 接着就是同步段,发送0x55
void Lin_SendSyncSegment(void){uart1_putchar(0x55);}
//然后就是发送PID(protect ID),这里的前六位为ID,后两位为校验位,函数功能为:输入ID,返回PID。
uint8_t Lin_CheckPID(uint8_t id)
{
        uint8_t P0 = (((id)^(id>>1)^(id>>2)^(id>>4))&0x01)<<6 ;
        uint8_t P1 = ((~((id>>1)^(id>>3)^(id>>4)^(id>>5)))&0x01)<<7 ;
        return (id|P0|P1) ;
}
// 该函数体就是单片机作为主机发送的帧头,可以指定ID发送帧头,接收从机返回的数据;也可以发送帧头+数据,让从机接收。
void Lin_Hearder(uint8_t id)
{
        Lin_SendBreak();
        Lin_SendSyncSegment();
        uart1_putchar(Lin_CheckPID(id));
}
// 此段函数功能:输入ID+数据,返回校验和段,里面有调用返回PID函数。诊断帧只能用标准校验这里还没有验证过,因为校验还没有测试。
// 是经典校验还是增强校验,另:诊断帧只能经典校验
uint8_t Lin_Checksum(uint8_t id , uint8_t data[])
{
        uint8_t t ;
        uint16_t sum ;

        sum = data[0];
        if(id == 0x3c)                        // 如果是诊断帧,用经典校验
        {
                for(t=1;t<8;t++)
                {
                        sum += data[t];
                        if(sum&0xff00)
                        {
                                sum&=0x00ff;
                                sum+=1;
                        }
                }
                sum = ~sum;        
                return (uint8_t)sum ;
        }
        for(t=1;t<8;t++)
        {
                sum += data[t];
                if(sum&0xff00)
                {
                        sum&=0x00ff;
                        sum+=1;
                }
        }
        sum+=Lin_CheckPID(id);
        if(sum&0xff00)
        {
                sum&=0x00ff;
                sum+=1;
        }
        sum = ~sum;        
        return (uint8_t)sum ;
}
//上面三个函数是单片机无论作为主机还是从机都需要用到的部分,所以在后面进行预编译选择的时候,放到外面。
//这里是主机的响应函数调用。
void Lin_Response(uint8_t id ,uint8_t data[])
{
        uart1_putbuf(data,8);
        uart1_putchar(Lin_Checksum(id,data));
}
void Lin_MainPutData(uint8_t id,uint8_t *data)
{
        Lin_Hearder(id);
        Lin_Response(id,data);
}
uint8_t uart1_getchar(void)
{
        TIMR_Start(TIMR2);
        TBtIdx = 0;RxBusy = 1;
        while(RxBusy){;}                                                                //等待接收完成
        return RxData;
}
void TIMR2_Handler(void)
{
        TIMR_INTClr(TIMR2);
        if(RBtIdx == 0){}else                                                        //起始位
        if(RBtIdx <  9){RxData>>=1;GPIO_InvBit(UART_RX_POINT);if(UART_RX_Value()){RxData|=0x80;}GPIO_InvBit(UART_RX_POINT);}else
        if(RBtIdx == 9){TIMR_Stop(TIMR2);RxBusy = 0;RBtIdx = 0;return;} //停止位
        RBtIdx++;
}
uint8_t Lin_MainGetData(uint8_t id,uint8_t *data)
{
        Lin_Hearder(id);                                                                //发送命令头
        while(UART_RX_Value()){;}                                                //等待起始位
        DelayUs((1000000*0.425)/LIN_BPS);                                //延时半个采样点
        for(int i=0;i<8;i++){data=uart1_getchar();}        //接收8字节数据
        uint8_t ReceiveCheckSum = uart1_getchar();                //接收校验和
        uint8_t SumCheck = Lin_Checksum(id,data);                //计算校验和
//        printf("ReceiveCheckSum & SumCheck: 0x%02x=0x%02x ",ReceiveCheckSum,SumCheck);
        if(ReceiveCheckSum == SumCheck)        {return 1;}                //校验正确
        return 0;
}        

/*
代码完毕部分内容参考了CSDN上的帖子
*/

#8 Re: Cortex M0/M3/M4/M7 » 9G-STM32 LwIP测试过程简介-缥缈九哥 » 2020-05-11 21:40:46

真的是很烦 说:

真是久仰大名, 10几年前的时候, 就经常在虾坛看到这个名字

大虾网那个是我。叫缥缈。

#9 Re: Cortex M0/M3/M4/M7 » 基于新唐M0516的MDK+GCC的编译环境建立与LOOK应用开发--缥缈九哥 » 2020-05-11 21:39:56

夏雨夜寐 说:

哈哈,九哥,你也来坑网了 big_smile
看帖子,你是把你博客的都搬过来了啊

是的,163上的帖子再不迁移过来就全军覆没了。。。。

#10 Re: Cortex M0/M3/M4/M7 » 9G-STM32 MDK-ARM开发过程简介--缥缈九哥 » 2020-05-11 21:38:45

lhb882 说:

有没有弄过stm32跑Linux得

STM32跑LINUX没有意义。

#13 Re: Cortex M0/M3/M4/M7 » 9G-STM32 MDK-ARM开发过程简介--缥缈九哥 » 2020-05-10 20:55:38

Lemi 说:

这个过程不是很基础吗,网上很容易搜到,此帖的过人之处在哪里?

入门简介,写给初学者的。以前的博客被网易干掉了,所有的笔记都访问不了,转到这边来保存。

#14 Re: Cortex M0/M3/M4/M7 » 9G-STM32 LwIP测试过程简介-缥缈九哥 » 2020-05-10 20:52:58

Lemi 说:

敢问大神,你与新塘的缥缈九哥N3290x系列教程可是同一位,还是慕名冠名的?

是的,我就是缥缈九哥。以前推广过新唐M0,M4的。

#15 Cortex M0/M3/M4/M7 » 基于新唐M0516LAN的SD5128的驱动测试 -- 缥缈九哥 » 2020-05-10 00:11:21

缥缈九哥
回复: 0

最近测试了一个SD5128的驱动,感觉可以 利用M0516LAN的串口来实现,写了一下测试程序,请大家核对一下是否可行。谢谢大家。
    附件源码如下:

#include <stdio.h>
#include "M051Series.h"
#include "Driver\DrvSYS.h"
#include "Driver\DrvUART.h"
#include "Driver\DrvGPIO.h"

//SD5128的逻辑0是25%的高75%的低,逻辑1是75%的高25%的低,那就是相当于开始25%是固定低,
//结束的25%是固定高,中间50%与逻辑相同,那么就可以简化为数据1000和1110代表逻辑0和逻辑1;
//SD5128的每个像素是3个字节的RGB数据,结束符是一位的低,25位的高,即可表示为0X7FFFFFFF
//串口UART起始位是低,结束位是高,刚好与上面的SD5128的逻辑相反,那么串口数据用6位,
//UART波形取反相后就能与SD5128的占空比符合,每个字符代表SD5128的两个BIT。编码关系如下:
//           __________________________________
//     |_ST_| D0 | D1 | D2 | D3 | D4 | D5 | SP |
//  00 | 0    1  1  1   0    1   1 1  | = 0x37
//  01 | 0   1  1  1   0    0   0 1  | = 0x07
//  10 | 0   0  0  1   0    1   1 1  | = 0x34
//  11 | 0   0  0  1   0    0   0 1  | = 0x04

unsigned char  BIT2BYTE[4]={0x37,0x07,0x34,0x04}; //BIT2BYTE
unsigned char  ENDCODE[4] ={0x7F,0xFF,0xFF,0xFF}; //ENDCODE
 
int SD5128_Init(void)
{
 STR_UART_T sParam;
    
 /* Set UART0 Pin */
 DrvGPIO_InitFunction(E_FUNC_UART0);

 /* Select UART0 Clock Source From 12Mhz*/
 DrvSYS_SelectIPClockSource(E_SYS_UART_CLKSRC,0);
 /* Select UART0 Clock Source From PLL*/
// DrvSYS_SelectIPClockSource(E_SYS_UART_CLKSRC,1);

 /* UART0 Setting */
    sParam.u32BaudRate   = 800000; //1000K
    sParam.u8cDataBits   = DRVUART_DATABITS_6;
    sParam.u8cStopBits   = DRVUART_STOPBITS_1;
    sParam.u8cParity   = DRVUART_PARITY_NONE;
    sParam.u8cRxTriggerLevel= DRVUART_FIFO_1BYTES;

 if(DrvUART_Open(UART_PORT0,&sParam) != E_SUCCESS)
 {
  printf("UART0 open failed\n");
  return FALSE;
 }
 return TRUE;
}

void SD5128_BYTE(unsigned char *buf,unsigned int length)
{
 int i;

 while(length--)
 {
  i=6;
  while(i>=0)
  {
   while(UART0->FSR.TX_FULL == 1);
   { 
    UART0->DATA = BIT2BYTE[(*buf>>i)&0x3];// printf(" 0x%02x",BIT2BYTE[(*buf>>i)&0x3]);
   }
   i=i-2;
  }
  buf++;
 }
}
void SD5128_Test(void)
{
 unsigned int i=0;
 unsigned char RGBDATA[3];   //RGB
 unsigned int  dly;

 printf("\n\r\n\r");
 printf("*** 9G-M0516 V1.00 Build by yuanxihua@21cn.com on ("__DATE__ " - " __TIME__ ")\n\r");
 printf("*** 9G-M0516 V1.00 Rebooting ...\n\r\n\r");
    
 SD5128_Init();
 while(1)
 {
  if(i++ > 0xFE) i=0;
  RGBDATA[0]=RGBDATA[1]=RGBDATA[2]=i; // printf("\n\ri=%02x |",i);
  SD5128_BYTE(RGBDATA,3);    // printf(" ||");//send rgbdata
  SD5128_BYTE(ENDCODE,4); //send endcode
  for(dly=0;dly<50;dly++) DrvSYS_Delay(1000); //delay 50ms
 }
}

代码结束。-缥缈九哥设计

#16 VMWare/Linux/Ubuntu/Fedora/CentOS/U-BOOT » 9G-LINUX嵌入式开发过程简介-缥缈九哥 » 2020-05-10 00:05:54

缥缈九哥
回复: 0

一,准备VMWARE+LINUX安装软件包

1,在http://www.ubuntu.com/getubuntu/download
    下载Ubuntu 8.04 LTS 的X86的Desktop版本的ISO
    http://mirror.lupaworld.com/ubuntu/releases/hardy/ubuntu-8.04.1-desktop-i386.iso
2,在http://www.3ddown.com/soft/33308.htm
    下载虚拟机(VMware Workstation) v6.5.0.118166 完整注册版
VMware.Workstation.v6.5.0.118166.exe
Flashget://W0ZMQVNIR0VUXWh0dHA6Ly93d3cuM2Rkb3duLmNvbS9kb3dubG9hZC5hc3A/aWQ9MzMzMDgmZHA9MSZmaWQ9MzJbRkxBU0hHRVRd&1029&1225512051
注意:记得抄下注册码:JU04H-A8Q82-T3J18-4WF67
或者下载注册机VMware.Workstation.v6.5.0.118166-Keygen.rar
3,在http://www.tuola.net/soft/view-1441.html
下载VanDyke SecureCRT v6.0.3 build 311 破解版
http://dl.tuola.net/s/SecureCRT.v6.0.3.rar
4,在ftp://ftp.denx.de/pub/eldk/4.1/arm-linux-x86/iso/
    下载arm-2007-01-21.iso
    ftp://ftp.denx.de/pub/eldk/4.1/arm-linux-x86/iso/arm-2007-01-21.iso
5, 在http://www.crsky.com/soft/2975.html
    下载Beyond_Compare_2.5.3.253_SC-special.exe
    http://3.scdx1.crsky.com/200807/Beyond_Compare_2.5.3.253_SC-special.exe
   
二,准备ARM+LINUX开发包

1,在http://www.kernel.org/pub/linux/kernel/v2.6/
    下载linux-2.6.26.tar.bz2
    http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.26.tar.bz2
2,在ftp://ftp.denx.de/pub/u-boot/
    下载u-boot-1.3.4.tar.bz2
ftp://ftp.denx.de/pub/u-boot/u-boot-1.3.4.tar.bz2
3,在http://busybox.net/
    下载BusyBox 1.11.1. (svn, patches, how to add a patch)
http://busybox.net/downloads/busybox-1.11.1.tar.bz2
4,在http://www.arm9.net/download.asp
    下载Jflash2440 ,一个Linux下Jtag烧写工具(含源代码)
http://www.arm9.com.cn/download/sbc2440v3/Jflash_linux.tgz
5,在http://blog.chinaunix.net/u/24474/showart_227846.html
下载Jflash-s3c2410_linux.tar.bz2
http://blogimg.chinaunix.net/blog/upfile/070107195410.bz2
注意:下载后把文件名改回Jflash-s3c2410_linux.tar.bz2

  可参考http://blog.chinaunix.net/u/23070/showart.php?id=157735的
Jflash-s3c2410源码分析(linux).pdf

可参考http://www.datasheetcatalog.org/datasheet2/5/0wd8ohcf4gti5jzkwhd33lhka1ky.pdf
Installation Manual for S3C2440 (linux)

三,安装VMWARE+LINUX开发平台

1,在XP系统上安装VMware-workstation-6.5.0-118166.exe
    A,双击VMware-workstation-6.5.0-118166.exe 启动安装,点击NEXT,选择Typical;再NEXT,安装文件夹选择
        默认;再NEXT,快捷方式产生用默认;再NEXT,按install;进入安装过程,输入使用者,公司和序列号
        JU04H-A8Q82-T3J18-4WF67 ,最后点击finish完成安装,重启动电脑;
    B,双击桌面VMware Workstation启动虚拟机程序,选择接受版权许可后点击OK后即可进入虚拟机界面使用;   

    注意:XP系统需要512MB以上内存,15GB以上硬盘空间。
   
2,在VMware Workstation上安装ubuntu-8.04.1-desktop的X86版本
    A,双击桌面VMware Workstation图标进入虚拟机,点击“New Virtual Machine”启动建立向导;选择Typical;再NEXT;
      选择“Install disc image file(iso)”,点击“Browse”找到存储在硬盘上的“ubuntu-8.04.1-desktop-i386.iso”文件;
      点击NEXT,在“Virtual Machine name”下面输入虚拟机文件名,在“Location”下面选择虚拟机文件夹安装位置;
      点击NEXT,在“Maxinum disk size”上增加到15GB以上,下面选择“Split Virtual disk to 2GB files”;点击NEXT,显示
      虚拟机配置信息,确认无误后点击“finish”即可进入安装过程;
    B,进入虚拟机的操作系统安装过程中,在“ubuntu-8.04.1-desktop-i386.iso”的安装界面中按F2功能键,用上下箭头选择
        “中文(简体)”再按“回车”;用上下箭头选择高亮“安装UBUNTU”时按回车;进入
        ubuntu-8.04.1-desktop 的X86版本的LiveCD界面,出现一个7步的“安装”向导;
    C,在安装向导上点击“前进”,地点用默认“上海”;点击“前进”,键盘布局用默认“China”;点击“前进”硬盘分区
        用默认“向导”,点击“前进”,输入安装用户名和密码;点击“前进”,在“准备安装”中,点击“安装";安装完成
        后,点击“现在重启”;并把虚拟机“VM”“Settings”中的“CD/DVD”改回“Use physical drive”;
       
    注意:XP系统需在DHCP的局域网内,要独立分配IP给虚拟机;安装的用户名和密码区别于ROOT用户,每次登陆系统及修改
        系统配置都要用到,需要牢记。

四,配置并更新ubuntu桌面系统

1,启动根用户和配置网络
A,进入系统后在启动菜单“应用程序”->“附件”->“终端”拉到桌面上;把启动菜单“位置”中的“计算机”也
        拉到桌面上;双击桌面“终端”中打开命令行终端
B,启用root用户并修改密码
        yuanxh@yuanxh-desktop:~$ sudo passwd root
C,进入root用户操作
        yuanxh@yuanxh-desktop:~$ su
D,查看本机IP配置信息
        root@yuanxh-desktop:/home/yuanxh# ifconfig -a
E,在启动菜单“系统”->“系统管理”->“网络”中
  填入IP,子域掩码,网关,DNS等网络参数;
F,修改.bashrc启用ll la l等到命令转义
  root@yuanxh-desktop:/home/yuanxh# vi /root/.bashrc
  root@yuanxh-desktop:/home/yuanxh# source /root/.bashrc
 
2,安装虚拟驱动Vmware tools
A,进入系统后在虚拟机菜单“VM”中点击“Install Vmware tools”后桌面会弹出一个CD-ROM内容的文件夹,里面有两个
  rpm和tar.gz压缩文件包;
B,双击桌面“终端”打开命令行终端,用命令模式安装虚拟驱动:
  切换到root用户
            yuanxh@yuanxh-desktop:~$ su
        建立文件夹
            root@yuanxh-desktop:/home/yuanxh# mkdir vm-tools
        修改文件夹权限
            root@yuanxh-desktop:/home/yuanxh# chmod 777 vm-tools/
        进入文件夹
            root@yuanxh-desktop:/home/yuanxh# cd vm-tools/
        复制虚拟驱动软件包
            root@yuanxh-desktop:/home/yuanxh/vm-tools# cp /media/cdrom0/VMwareTools-6.5.0-118166.tar.gz .
        解压虚拟驱动文件包
            root@yuanxh-desktop:/home/yuanxh/vm-tools# tar xzvf VMwareTools-6.5.0-118166.tar.gz
        进入虚拟驱动文件夹
            root@yuanxh-desktop:/home/yuanxh/vm-tools# cd vmware-tools-distrib/
        运行虚拟驱动安装脚本
            root@yuanxh-desktop:/home/yuanxh/vm-tools/vmware-tools-distrib# ./vmware-install.pl
C,一路按回车键,中间如果有一个编译跳不过,就输入N,再回车,直到最后能选择屏幕分辨率大小[15] 1152 X 864,
   并且鼠标能自由进入虚拟机和XP之间;
D,给vmtools升级
  如果VMware要更新版本的VMware Tools,先卸载旧的vmware tools
    root@yuanxh-desktop:/home/yuanxh/vm-tools/vmware-tools-distrib# ./bin/vmware-uninstall-tools.pl
  再重新安装新的vmware tools
   root@yuanxh-desktop:/home/yuanxh/vm-tools/vmware-tools-distrib# ./vmware-install.pl

3,启用XP与虚拟机系统间的共享文件夹功能
A,在虚拟机菜单“VM”->“settings”中,切换到“options”页;选择到“Shared Folders” 设置,选择“Always enabled”;
   点击“Folders”的“Add” 进入“add Shared Folder wizard”;再点击 NEXT,选择共享文件夹的“Host path”和“name”;点击“NEXT”配置好
  共享文件夹属性后,点击“Finish”;退出向导,点击“OK”退出设置;
B,在设置好共享文件夹后,并且安装好虚拟驱动后启动虚拟机,便可以在虚拟机中看到共享文件夹的内容;
     root@yuanxh-desktop:/home/yuanxh# ls -l  /mnt/hgfs
4,为虚拟机增加并口
A,双击桌面VMware Workstation图标进入虚拟机,先不要启动虚拟系统的电源,在虚拟机菜单“VM”->“settings”中,在“Hardware”页;
  点击窗口下面的“Add...” 进入“add Hardware wizard”;在Hardware Type 中选择“Parallel Port”;再点击 NEXT,在Parallel Port Type
  中选择默认的“Use physicial parallel port on the host”;再点击 NEXT,在physicial parallel port 中选择“LPT1”或者用“Auto detect”,
  在Device status 中选择上“Connect at power on”;最后点击“Finish”完成配置,点击“OK”退出添加硬件向导。
B,然后打开虚拟机电源,进入虚拟Linux系统,就可以使用并口了。其它串口中,USB口增加方式类似。
       
4,更新软件包服务器源后更新升级系统并安装SSH和ZMODEM协议
A,切换到root用户后执行以下命令更新升级系统:
  网络更新系统
        root@yuanxh-desktop:/home/yuanxh# apt-get update
        网络升级系统
        root@yuanxh-desktop:/home/yuanxh# apt-get upgrade
    B,网络安装SSH客户端和服务器端
        root@yuanxh-desktop:/home/yuanxh# apt-get install ssh openssh-server
        只有安装了这个才能用SecureCRT远程终端SSH访问系统
    C,用以下命令查找并安装ZMMODEM协议支持软件包:
        查找rzsz相关软件包
        root@yuanxh-desktop:~# apt-cache search rzsz
        显示lrzsz软件包详细情况
     root@yuanxh-desktop:~# apt-cache show lrzsz       
        网络安装zmodem传输协议
        root@yuanxh-desktop:/home/yuanxh# apt-get install lrzsz
        查看网络下载软件包存放目录
        root@yuanxh-desktop:/home/yuanxh# ll /var/cache/apt/archives/
D,安装开发必需软件包
  root@yuanxh-desktop:/usr/local/arm# apt-get install patch libncurses5-dev make rpm

5,安装SecureCRT远程终端SSH访问虚拟机和启用SFTP文件传输功能
A,双击SecureCRT.v6.0.3.rar里的scrt603.exe,点击“NEXT”;选择“接受协议”,再点击“NEXT”;用默认配置文件,点击“NEXT”
    后选择“Complete”;点击“NEXT”后产生快捷方式用默认;点击“Install”后进行安装,点击“Finish”完成安装;
B,把SecureCRT.v6.0.3.rar里的scrt603-tbe.exe解压到安装目录并运行,点击“patch”,然后对“SecureCRT.exe”破解30天限制使用
   权限;
C,利用SecureCRT的向导建立一个SSH会话到虚拟机;“下一步”后输入虚拟机IP地址和登陆用户名,建立好后双击会话SSH登陆LINUX,
  在会话属性中可配置终端类型,字体,滚屏行数,字符编码,XMODEM和SFTP默认路径等;
D,建立了到LINUX的SSH会话后,在Version 6.0.3 界面的菜单“File”->“Connect SFTP Tab”可启动到相应的LINUX的SFTP连接,
  在SFTP标签中输入“help”可以查看相关的SFTP命令。

五,建立FTP,NFS和交叉编译环境

1,用命令配置TFTP服务
    A, 建立TFTP系统根目录并修改权限
        root@yuanxh-desktop:/home/yuanxh/at91_works# mkdir  /tftpboot
        root@yuanxh-desktop:/home/yuanxh/at91_works# chmod 777  /tftpboot
    B,安装TFTP服务器端和客户端
        root@yuanxh-desktop:/# sudo apt-get install tftp tftpd openbsd-inetd
    C,修改配置文件使用TFTP根目录
        root@yuanxh-desktop:/home/yuanxh/at91_works# vi  /etc/inetd.conf
        在/etc/inetd.conf如下行中,后面路径改成/tftpboot
        tftp    dgram   udp     wait    nobody  /usr/sbin/tcpd /usr/sbin/in.tftpd /tftpboot
    D,启动服务
        root@yuanxh-desktop:/home/yuanxh/at91_works#  /etc/init.d/openbsd-inetd  restart
    E,测试服务
        root@yuanxh-desktop:/home/yuanxh# touch /tftpboot/aaa
        root@yuanxh-desktop:/home/yuanxh# vi /tftpboot/aaa
        root@yuanxh-desktop:/home/yuanxh# tftp 192.168.1.100
        tftp> get aaa
        tftp> quit
        root@yuanxh-desktop:/home/yuanxh# cat aaa

2,用命令配置NFS服务
    A,安装NFS服务器端
        root@yuanxh-desktop:/home/yuanxh# apt-get install nfs-kernel-server  nfs-common  portmap
    B,配置访问目录及权限
        root@yuanxh-desktop:/home/yuanxh/at91_works# mkdir  /nfsboot
        root@yuanxh-desktop:/home/yuanxh/at91_works# chmod 777  /nfsboot
        root@yuanxh-desktop:/home/yuanxh/at91_works# touch  /nfsboot/yuanxh
        root@yuanxh-desktop:/# vi /etc/exports
        在/etc/exports新行中填入以下内容
        /nfsboot  *(rw,sync)
    C,启动服务
        root@yuanxh-desktop:/# exportfs -ra
        root@yuanxh-desktop:/# /etc/init.d/portmap restart
        root@yuanxh-desktop:/# /etc/init.d/nfs-common restart
        root@yuanxh-desktop:/# /etc/init.d/nfs-kernel-server restart
    D,测试服务
        root@yuanxh-desktop:/# mount 192.168.1.100:/nfsboot  /mnt
        root@yuanxh-desktop:/home/yuanxh# ll /mnt
        root@yuanxh-desktop:/home/yuanxh# rm -rf /mnt/yuanxh
        root@yuanxh-desktop:/home/yuanxh# showmount
        root@yuanxh-desktop:/home/yuanxh# df
        root@yuanxh-desktop:/home/yuanxh# umount /mnt
        root@yuanxh-desktop:/home/yuanxh# ll /nfsboot
       
3,安装交叉编译工具链
    A,利用SecureCRT.v6.0.3登陆,传送文件到系统
        root@yuanxh-desktop:/home/yuanxh# mkdir /usr/local/arm
        root@yuanxh-desktop:/home/yuanxh# chmod 777 /usr/local/arm/
        root@yuanxh-desktop:/home/yuanxh# cd /usr/local/arm/
        root@yuanxh-desktop:/usr/local/arm# rz
        在SecureCRT弹出的窗口中选择交叉编译工具安装包arm-2007-01-21.iso
    B,安装ELDK交叉编译工具
     root@yuanxh-desktop:/usr/local/arm# cd /usr/local/
     root@yuanxh-desktop:/usr/local# mkdir eldk-4.1
        root@yuanxh-desktop:/usr/local# mount –o loop –t iso9660 arm-2007-01-21.iso /mnt/cdrom
        root@yuanxh-desktop:/usr/local# cp -av /mnt/cdrom/* eldk-4.1/
        root@yuanxh-desktop:/usr/local# cd eldk-4.1
        root@yuanxh-desktop:/usr/local/eldk-4.1# chmod 777 install
        root@yuanxh-desktop:/usr/local/eldk-4.1# ./install -d /usr/local/arm/eldk-4.1
  注意:eldk-4.1在ubuntu-8.04安装的rpm工具版本有问题,处理方法请查看
  http://lists.denx.de/pipermail/eldk/2008-July/000280.html
  在http://mirror.oss.lzu.edu.cn/software/embedded/eldk/4.2/ppc-linux-x86/distribution/RPMS/
  中下载rpm-4.4.2-46.i386.rpm ,rpm-build-4.4.2-46.i386.rpm,rpm-devel-4.4.2-46.i386.rpm
  在RPMS中增加rpm-4.4.2-46.i386.rpm ,rpm-build-4.4.2-46.i386.rpm,并在etc/rpm_cross.list 前两行中修改启用再安装。
     
    D,把编译器路径添加到系统路径中
        root@yuanxh-desktop:/usr/local/arm#  vi /root/.bashrc
        在alias l='ls -CF'后的空白处填上:
  PATH=$PATH:/usr/local/arm/eldk-4.1/usr/bin:/usr/local/arm/eldk-4.1/bin
  export PATH
  启动新系统路径
  root@yuanxh-desktop:/usr/local/arm# source /root/.bashrc
  显示新系统路径
  root@yuanxh-desktop:/usr/local/arm# echo $PATH
  查看版本号
  root@yuanxh-desktop:/usr/local/arm# arm-linux-gcc -v

六,编译U-BOOT启动代码

1,传送文件包到LINUX系统并解压
    A,利用SecureCRT.v6.0.3登陆,传送文件到系统
        root@yuanxh-desktop:/home/yuanxh# mkdir s3c2410
        root@yuanxh-desktop:/home/yuanxh# chmod 777 s3c2410/
        root@yuanxh-desktop:/home/yuanxh# cd s3c2410/
        root@yuanxh-desktop:/home/yuanxh/s3c2410# rz
        在SecureCRT弹出的窗口中选择u-boot-1.3.4.tar.bz2软件包
    B,解压软件包
        root@yuanxh-desktop:/home/yuanxh/s3c2410# tar xjvf u-boot-1.3.4.tar.bz2
       
2,编译生成U-BOOT启动目标码
    A,进入U-BOOT源码树
        root@yuanxh-desktop:/home/yuanxh/s3c2410# cd u-boot-1.3.4
    B,指定编译器
        root@yuanxh-desktop:/home/yuanxh/s3c2410/u-boot-1.3.4# vi Makefile
        把CROSS_COMPILE = arm-linux- 改成 CROSS_COMPILE=/usr/local/arm/eldk-4.1/usr/bin/arm-linux-
    C,配置并编译
        root@yuanxh-desktop:/home/yuanxh/s3c2410/u-boot-1.3.4# make clean
        root@yuanxh-desktop:/home/yuanxh/s3c2410/u-boot-1.3.4# make mrproper
        root@yuanxh-desktop:/home/yuanxh/s3c2410/u-boot-1.3.4# make smdk2410_config
        root@yuanxh-desktop:/home/yuanxh/s3c2410/u-boot-1.3.4# make
        root@yuanxh-desktop:/home/yuanxh/s3c2410/u-boot-1.3.4# mv u-boot.bin u-boot-smdk2410.bin
D,发送目标码
        root@yuanxh-desktop:/home/yuanxh/s3c2410/u-boot-1.3.4# sz u-boot-smdk2410.bin
       
3,编译生成Jflash工具
    A,利用SecureCRT.v6.0.3登陆,传送文件到系统
     root@yuanxh-desktop:/home/yuanxh/s3c2410# rz
     在SecureCRT弹出的窗口中选择Jflash-s3c2410_linux.tar.bz2软件包
     root@yuanxh-desktop:/home/yuanxh/s3c2410# mkdir Jflash-9gs3c2410
     root@yuanxh-desktop:/home/yuanxh/s3c2410# cd Jflash-9gs3c2410
B,解压软件包
  root@yuanxh-desktop:/home/yuanxh/s3c2410/Jflash-9gs3c2410# tar xvjf ../Jflash-s3c2410_linux.tar.bz2
C,在系统内指定内核头文件和体系结构头文件
  root@yuanxh-desktop:/home/yuanxh/s3c2410/Jflash-9gs3c2410# cd /usr/src
  root@yuanxh-desktop:/usr/src# ln -s linux-headers-2.6.24-19/ linux
  root@yuanxh-desktop:/usr/src# cd linux/include
  root@yuanxh-desktop:/usr/src/linux/include# ln -s asm-x86/ asm
D,在Makefile指定内核头文件和体系结构头文件路径
  root@yuanxh-desktop:/usr/src/linux/include# cd /home/yuanxh/s3c2410/Jflash-9gs3c2410/
  root@yuanxh-desktop:/home/yuanxh/s3c2410/Jflash-9gs3c2410# vi Makefile
  在 Makefile 的CFLAGS = -O2 -s -D__LINUX__ 后面添加上 -I/usr/src/linux/include/ 并保存退出
E,编译SJF生成目标码Jflash-s3c2410并执行
  root@yuanxh-desktop:/home/yuanxh/s3c2410/Jflash-9gs3c2410# make
  root@yuanxh-desktop:/home/yuanxh/s3c2410/Jflash-9gs3c2410# ./Jflash-s3c2410
F,同样的原理,用Jflash_linux.tgz,生成 Jflash-s3c2440 工具

4,用SJF工具烧启动代码到GEC2440开发板
A,按前面所说添加并口给虚拟机用,并把GEC2410_jtag V1.1 板的JP1并口与电脑并口接上,JP2的JTAG_2410口连接到GEC2440核心板
  开发板的J10的脚的标准JTAG口上,并打开开发板电源;
B,在Linux上运行:
  ./Jflash-s3c2440  u-boot-smdk2410.bin /t=5 /d=10
  如果连接上了会显示 S3C2440X(ID=0x0032409d) is detected.
C,在[K9S1208 NAND Flash JTAG Programmer]界面,K9S1208 is detected. ID=0xec76 会检测显示出来,
  在Select the function to test : 后输入0 并回车,确定0:K9S1208 Program 的功能;
D,在[SMC(K9S1208V0M) NAND Flash Writing Program]界面,Available target block number: 0~4095 会显示出来,
  在Input target block number: 后输入0 并回车,确定写入FLASH的首地址;
E,最后会在STATUS:后显示烧写过程Epppppppppppppppppppppppppppppppp好几行,基本是15秒种一个P,直到烧写完毕;
F,烧写完毕后显示0:K9S1208 Program      1:K9S1208 Pr BlkPage   2:Exit 时在 Select the function to test :
  后输入2并回车退出烧录工具。
 
5,移植u-boot-1.3.4到GEC2440开发板
A,修改Makefile
  root@yuanxh-desktop:/home/yuanxh/s3c2410/u-boot-1.3.4/board# vi Makefile
  在Makefile中的EXTRAVERSION = 后添加 -gec2440
  在Makefile中的smdk2410_config后增加如下两行:
   gec2440_config : unconfig
    @$(MKCONFIG) $(@:_config=) arm arm920t gec2440 NULL s3c24x0
B,在/board中添加GEC2440板定义
  root@yuanxh-desktop:/home/yuanxh/s3c2410/u-boot-1.3.4# cd board/
  root@yuanxh-desktop:/home/yuanxh/s3c2410/u-boot-1.3.4/board# cp -av smdk2410/ gec2440
  修改源文件和Makefile
  root@yuanxh-desktop:/home/yuanxh/s3c2410/u-boot-1.3.4/board# cd gec2440/
  root@yuanxh-desktop:/home/yuanxh/s3c2410/u-boot-1.3.4/board/gec2440# mv smdk2410.c gec2440.c
  root@yuanxh-desktop:/home/yuanxh/s3c2410/u-boot-1.3.4/board/gec2440# vi Makefile
  把COBJS   := smdk2410.o flash.o 改成 COBJS   := gec2440.o flash.o
C,在include/configs/中建立配置头文件
  root@yuanxh-desktop:/home/yuanxh/s3c2410/u-boot-1.3.4/board/gec2440# cd ../../include/configs/
  root@yuanxh-desktop:/home/yuanxh/s3c2410/u-boot-1.3.4/include/configs# cp smdk2410.h gec2440.h
D,试编译GEC2440开发板的U-BOOT目标码
  root@yuanxh-desktop:/home/yuanxh/s3c2410/u-boot-1.3.4/include/configs# cd ../../
  root@yuanxh-desktop:/home/yuanxh/s3c2410/u-boot-1.3.4# make mrproper
  root@yuanxh-desktop:/home/yuanxh/s3c2410/u-boot-1.3.4# make clean
  root@yuanxh-desktop:/home/yuanxh/s3c2410/u-boot-1.3.4# make distclean
  root@yuanxh-desktop:/home/yuanxh/s3c2410/u-boot-1.3.4# make gec2440_config
E,修改压缩成u-boot-1.3.4-gev2440.tar.gz
  root@yuanxh-desktop:/home/yuanxh/s3c2410# mv u-boot-1.3.4 u-boot-1.3.4-gev2440
  root@yuanxh-desktop:/home/yuanxh/s3c2410# tar czvf u-boot-1.3.4-gev2440.tar.gz u-boot-1.3.4-gev2440/
  root@yuanxh-desktop:/home/yuanxh/s3c2410# sz u-boot-1.3.4-gev2440.tar.gz
6,修改u-boot-1.3.4-gev2440.tar.gz源码
A,修改include/configs/gec2440.h 文件
  root@yuanxh-desktop:/home/yuanxh/s3c2410# cd u-boot-1.3.4-gev2440/include/configs/
  把
  #define CONFIG_S3C2410          1       /* in a SAMSUNG S3C2410 SoC     */
  #define CONFIG_SMDK2410          1       /* on a SAMSUNG SMDK2410 Board  */
  修改
  #define CONFIG_S3C2440          1       /* in a SAMSUNG S3C2440 SoC     */
  #define CONFIG_GEC2440          1       /* on a SAMSUNG GEC2440 Board  */

 
(调试完毕,但笔记尚未整理完成)
 
   
       
七,为S3C2410编译ARM-LINUX内核

1,传送文件包到LINUX系统并解压
    利用SecureCRT 登陆,传送文件到系统
        root@yuanxh-desktop:/home/yuanxh# cd s3c2410/
        root@yuanxh-desktop:/home/yuanxh/s3c2410# rz
        在SecureCRT弹出的窗口中选择linux-2.6.26.tar.bz2包;
2,解压内核
        root@yuanxh-desktop:/home/yuanxh/s3c2410# tar xjvf linux-2.6.26.tar.bz2
        root@yuanxh-desktop:/home/yuanxh/s3c2410# cd linux-2.6.26
3,为内核指定编译器
        root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26# vi Makefile
        把 EXTRAVERSION = -9gs3c2410 写上自己版本标识,指定体系结构和编译器
        ARCH           ?= arm
        CROSS_COMPILE  ?= /usr/local/arm/eldk-4.1/usr/bin/arm-linux-
        添加可加载模块安装路径
        INSTALL_MOD_PATH = $(TOPDIR)/modules-$(KERNELRELEASE)
4,编译内核及发布目标码
    A,查看内核支持的开发板
        root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26# make help
    B,配置为S3C2410板默认设置
        root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26# make s3c2410_defconfig
    C,编译生成全部目标码
        root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26# make
    D,也可分步依次生成zImage,可加载modules和安装可加载模拟到默认目录
        root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26# make zImage
        root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26# make modules
        root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26# make modules_install
    E,发送内核目标码和可加载模块
        root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26# cp arch/arm/boot/zImage .
        root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26# mv zImage zImage-2.6.26-gec2440.bin
        root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26# sz zImage-2.6.26-gec2440.bin
        root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26# tar czvf modules-2.6.26-gec2440.tar.gz modules-2.6.26-gec2440/
        root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26# sz modules-2.6.26-gec2440.tar.gz
F,个性化配置内核
  root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26# make menuconfig
  .config中内核启动命令行参数CONFIG_CMDLINE改为:
  mem=64M console=ttySAC0,115200 initrd=0x32000000,8388608 root=/dev/ram0 rw init=/linuxrc
G,编译生成U-BOOT可识别目标码uImage
  root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26# make uImage
  root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26# cp arch/arm/boot/uImage .
  root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26# mv uImage uImage-2.6.26-gec2440.bin
        root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26# sz uImage-2.6.26-gec2440.bin
5,清除内核目标码恢复未配置状态
        root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26# make clean
        root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26# make distclean
        root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26# make mrproper
6,修改linux-2.6.26代码适合GEC2440开发板
A,修改初时钟始化
  root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26# vi arch/arm/mach-s3c2440/mach-smdk2440.c
  注释掉原来的时钟初始化函数:
  //      s3c24xx_init_clocks(16934400);  // charge by yuanxihua@21cn.com
  增加上新的时钟初始化定义:
        s3c24xx_init_clocks(12000000);
    B,重新编译内核
     root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26# ./mkall
     执行的脚本内容如下:
     #!/bin/sh
  #make by yuanxihua@21cn.com  for GEC2440
  #make s3c2410_defconfig
  make
  make uImage
  cp arch/arm/boot/uImage uImage-2.6.26-9g24x0.bin
  cp uImage-2.6.26-9g24x0.bin /tftpboot
  make modules_install INSTALL_MOD_PATH=./modules-2.6.26-9g24x0
  tar czvf modules-2.6.26-9g24x0.tar.gz ./modules-2.6.26-9g24x0
  cp modules-2.6.26-9g24x0.tar.gz  /tftpboot
C,修改网络CS8900问题
  修改Kconfig
  root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26-9g24x0# cd drivers/net/
  root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26-9g24x0/drivers/net# vi Kconfig

(调试完毕,但笔记尚未整理完成)

  D,修改LCD驱动问题

#17 华芯微特 » 基于华芯微特SWM320的SPI接口的24位ADC的AD7124驱动开发--缥缈九哥 » 2020-05-09 21:58:34

缥缈九哥
回复: 1

C文件

/********************************************************************************/
/* @file	ad7124.c															*/
/* @version	V1.00																*/
/* $author:	yuanxihua@21cn.com													*/
/* $Date: 	2019/03/04 02:54 $ 													*/
/* @brief 	SWM320RBT6 Series AD7124 Driver Sample Code							*/
/*																				*/
/* @note																		*/
/* Copyright (C) 2010-2019 PM9GZY Technology Corp. All rights reserved.			*/
/*																				*/
/********************************************************************************/ 
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "ad7124.h"
/*
_________________________________________________
|	SWM320RBT6						AD7124		|
|												|
|	PP1		MISO1		<----		MISO		|
|	PP2		MOSI1		---->		MOSI		|
|	PP3		SCLK1		---->		SCLK		|
|	PP4		NSS1		---->		ANCS		|
|_______________________________________________|
*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define AD7124_CS_L()		GPIO_ClrBit(GPIOP, PIN4)
#define AD7124_CS_H()		GPIO_SetBit(GPIOP, PIN4)
/* Private macro -------------------------------------------------------------*/
#define INVALID_VAL 		-1 /* Invalid argument */
#define COMM_ERR    		-2 /* Communication error on receive */
#define TIMEOUT     		-3 /* A timeout has occured */
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
void AD7124_Init(void);
void AD7124_Reset(void);
/* Private functions ---------------------------------------------------------*/
void SPI1Init(void)
{
	SPI_InitStructure SPI_initStruct;

	PORT_Init(PORTP, PIN1, FUNMUX1_SPI1_MISO, 1);
	PORT_Init(PORTP, PIN2, FUNMUX0_SPI1_MOSI, 0);
	PORT_Init(PORTP, PIN3, FUNMUX1_SPI1_SCLK, 0);
	GPIO_Init(GPIOP, PIN4, 1, 0, 0);AD7124_CS_H();//PORT_Init(PORTP, PIN4, FUNMUX0_SPI1_SSEL, 0);
	
	SPI_initStruct.clkDiv 		= SPI_CLKDIV_64;//0.52US
	SPI_initStruct.FrameFormat 	= SPI_FORMAT_SPI;
	SPI_initStruct.SampleEdge 	= SPI_FIRST_EDGE;
	SPI_initStruct.IdleLevel 	= SPI_LOW_LEVEL;
	SPI_initStruct.WordSize 	= 8;
	SPI_initStruct.Master 		= 1;
	SPI_initStruct.RXHFullIEn 	= 0;
	SPI_initStruct.TXEmptyIEn 	= 0;
	SPI_initStruct.TXCompleteIEn = 0;
	SPI_Init(SPI1, &SPI_initStruct);
	
	SPI_Open(SPI1);
	AD7124_Reset();
	AD7124_Init();
}
void AD7124_Read_Register(ad7124_reg_t *reg)
{
	uint8_t cmd=reg->addr+0x40,width=reg->size,admit=reg->rw;uint32_t val=0;
	if(!(admit&AD7124_RO)){return;}
	AD7124_CS_L();
	SPI_ReadWrite(SPI1,cmd);while(width--){val<<=8;val|=SPI_ReadWrite(SPI1,0x55)&0xff;}reg->value=val;
	AD7124_CS_H();
}
void AD7124_Write_Register(ad7124_reg_t *reg)
{
	uint8_t cmd=reg->addr+0x00,width=reg->size,admit=reg->rw;uint32_t val=reg->value;
	if(!(admit&AD7124_WO)){return;}
	AD7124_CS_L();
	SPI_ReadWrite(SPI1,cmd);while(width--){SPI_ReadWrite(SPI1,(val>>(width*8))&0xff);}
	AD7124_CS_H();
}
void AD7124_Reset(void){AD7124_CS_L();for(uint8_t i=0;i<8;i++){SPI_ReadWrite(SPI1,0xFF);}AD7124_CS_H();osDelay(10);}
void AD7124_Init(void){for(uint8_t i=AD7124_Status;i<AD7124_REG_END;i++){AD7124_Write_Register(&ad7124_regs[i]);}}
uint8_t AD7124_CRC8(uint8_t *buf, uint8_t len)
{
    uint8_t i,crc=0,MULA=AD7124_CRC8_POLYNOMIAL_REPRESENTATION;
    while(len--){for(i=0x80;i!=0;i>>=1){if(((crc&0x80)!=0)!=((*buf&i)!=0)){crc<<=1;crc^=MULA;}else{crc<<=1;}}buf++;}
    return crc;
}

void AD7124_Gain(void){}
uint8_t AD7124_Read(uint32_t *data)
{
	int32_t timeout=1000000;uint8_t total=0;
	uint8_t lastch=20;uint8_t nowch=20;
	
	while(1)
	{
		while(--timeout)
		{
			/* Read the value of the Status Register */
			AD7124_Read_Register(&ad7124_regs[AD7124_Status]);
			/* Check the RDY bit in the Status Register */
			if((ad7124_regs[AD7124_Status].value & AD7124_STATUS_REG_RDY)==0) 
			{nowch = AD7124_STATUS_REG_CH_ACTIVE(ad7124_regs[AD7124_Status].value);break;} 
		}
		if(timeout<=0){printf("AD Conv Timeout!!!\n\r");return total;}
		if(lastch!=nowch)
		{
			/* Read the value of the Data Register */
			AD7124_Read_Register(&ad7124_regs[AD7124_Data]);
			/* Get the read result */
			data[nowch] = ad7124_regs[AD7124_Data].value; data[nowch]&=0xFFFFFF;
			lastch=nowch;total++;
//			printf("AD7124_Read data[%d] = 0x%08x \n\r",nowch,data[nowch]);
		}
		if(total>=4){break;}
	}		
	return total;
}

void AD7124_Test(void)
{
	uint32_t adc[4]={0};float val[4];	
//	AD7124_CS_L(); SPI_ReadWrite(SPI1,0x55);AD7124_CS_H();
//	AD7124_Read_Register(&ad7124_regs[AD7124_ID]);
//	printf("AD7124_ID = 0x%02x \n\r",ad7124_regs[AD7124_ID].value);	

//	AD7124_Read_Register(&ad7124_regs[AD7124_CHANNEL_0]);
//	printf("AD7124_CHANNEL_0 = 0x%08x \n\r",ad7124_regs[AD7124_CHANNEL_0].value);	
	
//	ad7124_regs[AD7124_FILTER_0].value=0x555555;
//	AD7124_Write_Register(&ad7124_regs[AD7124_FILTER_0]);
//	AD7124_Read_Register(&ad7124_regs[AD7124_FILTER_0]);
//	printf("AD7124_FILTER_0 = 0x%08x \n\r",ad7124_regs[AD7124_FILTER_0].value);	

//	for(uint8_t i=AD7124_Status;i<AD7124_REG_END;i++)
//	{
//		AD7124_Read_Register(&ad7124_regs[i]);
//		printf("ad7124_regs[0x%02x]=0x%08x \n\r",i,ad7124_regs[i].value);	
//	}

	AD7124_Read(adc);
//	printf("ADC[0]=0x%08x,ADC[1]=0x%08x,ADC[2]=0x%08x,ADC[3]=0x%08x\n\r",adc[0],adc[1],adc[2],adc[3]);
	for(uint8_t i=0;i<4;i++)
	{
		val[i]=adc[i];val[i]*=2.500;val[i]/=0xffffff;
	}
	val[0]/=128;val[1]/=16;val[2]/=4;val[3]/=1;
//	printf("VAL[0]=%3.10f V\n\r",val[0]);
//	printf("VAL[1]=%3.10f V\n\r",val[1]);
//	printf("VAL[2]=%3.10f V\n\r",val[2]);
//	printf("VAL[3]=%3.10f V\n\r",val[3]);
//	val[0]*=1000;val[1]*=1000;val[2]*=1000;val[3]*=1000;
	printf("%3.10f,%3.10f,%3.10f,%3.10f\n\r",val[0],val[1],val[2],val[3]);
	OLED_Volute(val);
	osDelay(200);
}

H文件

#ifndef __AD7124_H__
#define __AD7124_H__

#define AD7124_CRC8_POLYNOMIAL_REPRESENTATION		0x07 	/* x8 + x2 + x + 1 */

#define AD7124_WO 1   /* Write */
#define	AD7124_RO 2   /* Read */
#define	AD7124_RW 3   /* Read and Write */

/* AD7124 Register Map */
#define AD7124_COMM_REG      0x00
#define AD7124_STATUS_REG    0x00
#define AD7124_ADC_CTRL_REG  0x01
#define AD7124_DATA_REG      0x02
#define AD7124_IO_CTRL1_REG  0x03
#define AD7124_IO_CTRL2_REG  0x04
#define AD7124_ID_REG        0x05
#define AD7124_ERR_REG       0x06
#define AD7124_ERREN_REG     0x07
#define AD7124_CH0_MAP_REG   0x09
#define AD7124_CH1_MAP_REG   0x0A
#define AD7124_CH2_MAP_REG   0x0B
#define AD7124_CH3_MAP_REG   0x0C
#define AD7124_CH4_MAP_REG   0x0D
#define AD7124_CH5_MAP_REG   0x0E
#define AD7124_CH6_MAP_REG   0x0F
#define AD7124_CH7_MAP_REG   0x10
#define AD7124_CH8_MAP_REG   0x11
#define AD7124_CH9_MAP_REG   0x12
#define AD7124_CH10_MAP_REG  0x13
#define AD7124_CH11_MAP_REG  0x14
#define AD7124_CH12_MAP_REG  0x15
#define AD7124_CH13_MAP_REG  0x16
#define AD7124_CH14_MAP_REG  0x17
#define AD7124_CH15_MAP_REG  0x18
#define AD7124_CFG0_REG      0x19
#define AD7124_CFG1_REG      0x1A
#define AD7124_CFG2_REG      0x1B
#define AD7124_CFG3_REG      0x1C
#define AD7124_CFG4_REG      0x1D
#define AD7124_CFG5_REG      0x1E
#define AD7124_CFG6_REG      0x1F
#define AD7124_CFG7_REG      0x20
#define AD7124_FILT0_REG     0x21
#define AD7124_FILT1_REG     0x22
#define AD7124_FILT2_REG     0x23
#define AD7124_FILT3_REG     0x24
#define AD7124_FILT4_REG     0x25
#define AD7124_FILT5_REG     0x26
#define AD7124_FILT6_REG     0x27
#define AD7124_FILT7_REG     0x28
#define AD7124_OFFS0_REG     0x29
#define AD7124_OFFS1_REG     0x2A
#define AD7124_OFFS2_REG     0x2B
#define AD7124_OFFS3_REG     0x2C
#define AD7124_OFFS4_REG     0x2D
#define AD7124_OFFS5_REG     0x2E
#define AD7124_OFFS6_REG     0x2F
#define AD7124_OFFS7_REG     0x30
#define AD7124_GAIN0_REG     0x31
#define AD7124_GAIN1_REG     0x32
#define AD7124_GAIN2_REG     0x33
#define AD7124_GAIN3_REG     0x34
#define AD7124_GAIN4_REG     0x35
#define AD7124_GAIN5_REG     0x36
#define AD7124_GAIN6_REG     0x37
#define AD7124_GAIN7_REG     0x38

/* Communication Register bits */
#define AD7124_COMM_REG_WEN    					(0 << 7)
#define AD7124_COMM_REG_WR     					(0 << 6)
#define AD7124_COMM_REG_RD     					(1 << 6)
#define AD7124_COMM_REG_RA(x)  					((x) & 0x3F)

/* Status Register bits */
#define AD7124_STATUS_REG_RDY          			(1 << 7)
#define AD7124_STATUS_REG_ERROR_FLAG   			(1 << 6)
#define AD7124_STATUS_REG_POR_FLAG     			(1 << 4)
#define AD7124_STATUS_REG_CH_ACTIVE(x) 			((x) & 0xF)

/* ADC_Control Register bits */
#define AD7124_ADC_CTRL_REG_DOUT_RDY_DEL   		(1 << 12)
#define AD7124_ADC_CTRL_REG_CONT_READ      		(1 << 11)
#define AD7124_ADC_CTRL_REG_DATA_STATUS    		(1 << 10)
#define AD7124_ADC_CTRL_REG_CS_EN          		(1 << 9)
#define AD7124_ADC_CTRL_REG_REF_EN         		(1 << 8)
#define AD7124_ADC_CTRL_REG_POWER_MODE(x)  		(((x) & 0x3) << 6)
#define AD7124_ADC_CTRL_REG_MODE(x)        		(((x) & 0xF) << 2)
#define AD7124_ADC_CTRL_REG_CLK_SEL(x))    		(((x) & 0x3) << 0)

/* IO_Control_1 Register bits */
#define AD7124_IO_CTRL1_REG_GPIO_DAT2     		(1 << 23)
#define AD7124_IO_CTRL1_REG_GPIO_DAT1     		(1 << 22)
#define AD7124_IO_CTRL1_REG_GPIO_CTRL2    		(1 << 19)
#define AD7124_IO_CTRL1_REG_GPIO_CTRL1    		(1 << 18)
#define AD7124_IO_CTRL1_REG_PDSW          		(1 << 15)
#define AD7124_IO_CTRL1_REG_IOUT1(x)      		(((x) & 0x7) << 11)
#define AD7124_IO_CTRL1_REG_IOUT0(x)      		(((x) & 0x7) << 8)
#define AD7124_IO_CTRL1_REG_IOUT_CH1(x)   		(((x) & 0xF) << 4)
#define AD7124_IO_CTRL1_REG_IOUT_CH0(x)   		(((x) & 0xF) << 0)

/*IO_Control_1 AD7124-8 specific bits */
#define AD7124_8_IO_CTRL1_REG_GPIO_DAT4 		(1 << 23)
#define AD7124_8_IO_CTRL1_REG_GPIO_DAT3     	(1 << 22)
#define AD7124_8_IO_CTRL1_REG_GPIO_DAT2     	(1 << 21)
#define AD7124_8_IO_CTRL1_REG_GPIO_DAT1     	(1 << 20)
#define AD7124_8_IO_CTRL1_REG_GPIO_CTRL4    	(1 << 19)
#define AD7124_8_IO_CTRL1_REG_GPIO_CTRL3    	(1 << 18)
#define AD7124_8_IO_CTRL1_REG_GPIO_CTRL2    	(1 << 17)
#define AD7124_8_IO_CTRL1_REG_GPIO_CTRL1    	(1 << 16)

/* IO_Control_2 Register bits */
#define AD7124_IO_CTRL2_REG_GPIO_VBIAS7   		(1 << 15)
#define AD7124_IO_CTRL2_REG_GPIO_VBIAS6   		(1 << 14)
#define AD7124_IO_CTRL2_REG_GPIO_VBIAS5   		(1 << 11)
#define AD7124_IO_CTRL2_REG_GPIO_VBIAS4   		(1 << 10)
#define AD7124_IO_CTRL2_REG_GPIO_VBIAS3   		(1 << 5)
#define AD7124_IO_CTRL2_REG_GPIO_VBIAS2   		(1 << 4)
#define AD7124_IO_CTRL2_REG_GPIO_VBIAS1   		(1 << 1)
#define AD7124_IO_CTRL2_REG_GPIO_VBIAS0   		(1 << 0)

/*IO_Control_2 AD7124-8 specific bits */
#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS15  	(1 << 15)
#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS14  	(1 << 14)
#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS13  	(1 << 13)
#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS12  	(1 << 12)
#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS11  	(1 << 11)
#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS10  	(1 << 10)
#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS9   	(1 << 9)
#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS8   	(1 << 8)
#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS7   	(1 << 7)
#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS6   	(1 << 6)
#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS5   	(1 << 5)
#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS4   	(1 << 4)
#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS3   	(1 << 3)
#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS2   	(1 << 2)
#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS1   	(1 << 1)
#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS0   	(1 << 0)

/* ID Register bits */
#define AD7124_ID_REG_DEVICE_ID(x)   			(((x) & 0xF) << 4)
#define AD7124_ID_REG_SILICON_REV(x) 			(((x) & 0xF) << 0)

/* Error Register bits */
#define AD7124_ERR_REG_LDO_CAP_ERR        		(1 << 19)
#define AD7124_ERR_REG_ADC_CAL_ERR        		(1 << 18)
#define AD7124_ERR_REG_ADC_CONV_ERR       		(1 << 17)
#define AD7124_ERR_REG_ADC_SAT_ERR        		(1 << 16)
#define AD7124_ERR_REG_AINP_OV_ERR        		(1 << 15)
#define AD7124_ERR_REG_AINP_UV_ERR        		(1 << 14)
#define AD7124_ERR_REG_AINM_OV_ERR        		(1 << 13)
#define AD7124_ERR_REG_AINM_UV_ERR        		(1 << 12)
#define AD7124_ERR_REG_REF_DET_ERR        		(1 << 11)
#define AD7124_ERR_REG_DLDO_PSM_ERR       		(1 << 9)
#define AD7124_ERR_REG_ALDO_PSM_ERR       		(1 << 7)
#define AD7124_ERR_REG_SPI_IGNORE_ERR     		(1 << 6)
#define AD7124_ERR_REG_SPI_SLCK_CNT_ERR   		(1 << 5)
#define AD7124_ERR_REG_SPI_READ_ERR       		(1 << 4)
#define AD7124_ERR_REG_SPI_WRITE_ERR      		(1 << 3)
#define AD7124_ERR_REG_SPI_CRC_ERR        		(1 << 2)
#define AD7124_ERR_REG_MM_CRC_ERR         		(1 << 1)

/* Error_En Register bits */
#define AD7124_ERREN_REG_MCLK_CNT_EN           	(1 << 22)
#define AD7124_ERREN_REG_LDO_CAP_CHK_TEST_EN   	(1 << 21)
#define AD7124_ERREN_REG_LDO_CAP_CHK(x)        	(((x) & 0x3) << 19)
#define AD7124_ERREN_REG_ADC_CAL_ERR_EN        	(1 << 18)
#define AD7124_ERREN_REG_ADC_CONV_ERR_EN       	(1 << 17)
#define AD7124_ERREN_REG_ADC_SAT_ERR_EN        	(1 << 16)
#define AD7124_ERREN_REG_AINP_OV_ERR_EN        	(1 << 15)
#define AD7124_ERREN_REG_AINP_UV_ERR_EN       	(1 << 14)
#define AD7124_ERREN_REG_AINM_OV_ERR_EN       	(1 << 13)
#define AD7124_ERREN_REG_AINM_UV_ERR_EN        	(1 << 12)
#define AD7124_ERREN_REG_REF_DET_ERR_EN       	(1 << 11)
#define AD7124_ERREN_REG_DLDO_PSM_TRIP_TEST_EN 	(1 << 10)
#define AD7124_ERREN_REG_DLDO_PSM_ERR_ERR      	(1 << 9)
#define AD7124_ERREN_REG_ALDO_PSM_TRIP_TEST_EN 	(1 << 8)
#define AD7124_ERREN_REG_ALDO_PSM_ERR_EN       	(1 << 7)
#define AD7124_ERREN_REG_SPI_IGNORE_ERR_EN     	(1 << 6)
#define AD7124_ERREN_REG_SPI_SCLK_CNT_ERR_EN   	(1 << 5)
#define AD7124_ERREN_REG_SPI_READ_ERR_EN       	(1 << 4)
#define AD7124_ERREN_REG_SPI_WRITE_ERR_EN      	(1 << 3)
#define AD7124_ERREN_REG_SPI_CRC_ERR_EN        	(1 << 2)
#define AD7124_ERREN_REG_MM_CRC_ERR_EN         	(1 << 1)

/* Channel Registers 0-15 bits */
#define AD7124_CH_MAP_REG_CH_ENABLE    			(1 << 15)
#define AD7124_CH_MAP_REG_SETUP(x)     			(((x) & 0x7) << 12)
#define AD7124_CH_MAP_REG_AINP(x)      			(((x) & 0x1F) << 5)    
#define AD7124_CH_MAP_REG_AINM(x)      			(((x) & 0x1F) << 0)

/* Configuration Registers 0-7 bits */
#define AD7124_CFG_REG_BIPOLAR     				(1 << 11)
#define AD7124_CFG_REG_BURNOUT(x)  				(((x) & 0x3) << 9)
#define AD7124_CFG_REG_REF_BUFP    				(1 << 8)
#define AD7124_CFG_REG_REF_BUFM    				(1 << 7)
#define AD7124_CFG_REG_AIN_BUFP    				(1 << 6)
#define AD7124_CFG_REG_AINN_BUFM   				(1 << 5)
#define AD7124_CFG_REG_REF_SEL(x)  				((x) & 0x3) << 3
#define AD7124_CFG_REG_PGA(x)      				(((x) & 0x7) << 0)

/* Filter Register 0-7 bits */
#define AD7124_FILT_REG_FILTER(x)         		(((x) & 0x7) << 21)
#define AD7124_FILT_REG_REJ60             		(1 << 20)
#define AD7124_FILT_REG_POST_FILTER(x)    		(((x) & 0x7) << 17)
#define AD7124_FILT_REG_SINGLE_CYCLE      		(1 << 16)
#define AD7124_FILT_REG_FS(x)             		(((x) & 0x7FF) << 0)

/*! Device register info */
typedef struct 
{
	uint8_t addr;
	int32_t value;
	uint8_t size;
	uint8_t rw;
}ad7124_reg_t;

/*! Array holding the info for the ad7124 registers - address, initial value,
    size and access type. */
ad7124_reg_t ad7124_regs[] =
{
	{0x00,     0x00, 1, AD7124_RO}, /* AD7124_Status */
	//使能DATA_STATUS、REF_EN 和 FULL POWER的连续采样模式,禁止用DOUT_RDY_DEL、CONT_READ和CS_EN,内时钟CLK无输出
	{0x01,   0x0580, 2, AD7124_RW}, /* AD7124_ADC_Control */
	{0x02, 0x000000, 3, AD7124_RO}, /* AD7124_Data */
	//禁用IOUT0、IOUT1、不用PDSW低边桥开关
	{0x03, 0x000000, 3, AD7124_RW}, /* AD7124_IOCon1 */
	//禁用VBIAS0-VBIAS7
	{0x04,   0x0000, 2, AD7124_RW}, /* AD7124_IOCon2 */
	{0x05,     0x04, 1, AD7124_RO}, /* AD7124_ID */
	{0x06, 0x000000, 3, AD7124_RO}, /* AD7124_Error */
	//不用ERROR功能
	{0x07, 0x000000, 3, AD7124_RW}, /* AD7124_Error_En */
	{0x08,     0x00, 1, AD7124_RO}, /* AD7124_Mclk_Count */
	//使能通道0、选择Setup0配置组、输入脚分配AIN0->AINP,AIN1->AINM
	{0x09,   0x8001, 2, AD7124_RW}, /* AD7124_Channel_0 */
	//使能通道1、选择Setup1配置组、输入脚分配AIN2->AINP,AIN3->AINM
	{0x0A,   0x9043, 2, AD7124_RW}, /* AD7124_Channel_1 */
	//使能通道2、选择Setup2配置组、输入脚分配AIN4->AINP,AIN5->AINM
	{0x0B,   0xA085, 2, AD7124_RW}, /* AD7124_Channel_2 */
	//使能通道3、选择Setup3配置组、输入脚分配AIN6->AINP,AIN7->AINM
	{0x0C,   0xB0C7, 2, AD7124_RW}, /* AD7124_Channel_3 */
	{0x0D,   0x0000, 2, AD7124_RW}, /* AD7124_Channel_4 */
	{0x0E,   0x0000, 2, AD7124_RW}, /* AD7124_Channel_5 */
	{0x0F,   0x0000, 2, AD7124_RW}, /* AD7124_Channel_6 */
	{0x10,   0x0000, 2, AD7124_RW}, /* AD7124_Channel_7 */
	{0x11,   0x0000, 2, AD7124_RW}, /* AD7124_Channel_8 */
	{0x12,   0x0000, 2, AD7124_RW}, /* AD7124_Channel_9 */
	{0x13,   0x0000, 2, AD7124_RW}, /* AD7124_Channel_10 */
	{0x14,   0x0000, 2, AD7124_RW}, /* AD7124_Channel_11 */
	{0x15,   0x0000, 2, AD7124_RW}, /* AD7124_Channel_12 */
	{0x16,   0x0000, 2, AD7124_RW}, /* AD7124_Channel_13 */
	{0x17,   0x0000, 2, AD7124_RW}, /* AD7124_Channel_14 */
	{0x18,   0x0000, 2, AD7124_RW}, /* AD7124_Channel_15 */
	//使能单极性、REF_BUF、AIN_BUF缓冲和REF_SEL内部基准、PGA=128
	{0x19,   0x01F7, 2, AD7124_RW}, /* AD7124_Config_0 */
	//使能单极性、REF_BUF、AIN_BUF缓冲和REF_SEL内部基准、PGA=16
	{0x1A,   0x01F4, 2, AD7124_RW}, /* AD7124_Config_1 */
	//使能单极性、REF_BUF、AIN_BUF缓冲和REF_SEL内部基准、PGA=4
	{0x1B,   0x01F2, 2, AD7124_RW}, /* AD7124_Config_2 */
	//使能单极性、REF_BUF、AIN_BUF缓冲和REF_SEL内部基准、PGA=1
	{0x1C,   0x01F0, 2, AD7124_RW}, /* AD7124_Config_3 */
	{0x1D,   0x09F0, 2, AD7124_RW}, /* AD7124_Config_4 */
	{0x1E,   0x09F0, 2, AD7124_RW}, /* AD7124_Config_5 */
	{0x1F,   0x09F0, 2, AD7124_RW}, /* AD7124_Config_6 */
	{0x20,   0x09F0, 2, AD7124_RW}, /* AD7124_Config_7 */
	{0x21, 0x160180, 3, AD7124_RW}, /* AD7124_Filter_0 */
	{0x22, 0x160180, 3, AD7124_RW}, /* AD7124_Filter_1 */
	{0x23, 0x160180, 3, AD7124_RW}, /* AD7124_Filter_2 */
	{0x24, 0x160180, 3, AD7124_RW}, /* AD7124_Filter_3 */
	{0x25, 0x160180, 3, AD7124_RW}, /* AD7124_Filter_4 */
	{0x26, 0x160180, 3, AD7124_RW}, /* AD7124_Filter_5 */
	{0x27, 0x160180, 3, AD7124_RW}, /* AD7124_Filter_6 */
	{0x28, 0x160180, 3, AD7124_RW}, /* AD7124_Filter_7 */
	{0x29, 0x800000, 3, AD7124_RW}, /* AD7124_Offset_0 */
	{0x2A, 0x800000, 3, AD7124_RW}, /* AD7124_Offset_1 */
	{0x2B, 0x800000, 3, AD7124_RW}, /* AD7124_Offset_2 */
	{0x2C, 0x800000, 3, AD7124_RW}, /* AD7124_Offset_3 */
	{0x2D, 0x800000, 3, AD7124_RW}, /* AD7124_Offset_4 */
	{0x2E, 0x800000, 3, AD7124_RW}, /* AD7124_Offset_5 */
	{0x2F, 0x800000, 3, AD7124_RW}, /* AD7124_Offset_6 */
	{0x30, 0x800000, 3, AD7124_RW}, /* AD7124_Offset_7 */
	//增益寄存器
	{0x31, 0x500000, 3, AD7124_RW}, /* AD7124_Gain_0 */
	//增益寄存器
	{0x32, 0x500000, 3, AD7124_RW}, /* AD7124_Gain_1 */
	//增益寄存器
	{0x33, 0x500000, 3, AD7124_RW}, /* AD7124_Gain_2 */
	//增益寄存器
	{0x34, 0x500000, 3, AD7124_RW}, /* AD7124_Gain_3 */
	{0x35, 0x500000, 3, AD7124_RW}, /* AD7124_Gain_4 */
	{0x36, 0x500000, 3, AD7124_RW}, /* AD7124_Gain_5 */
	{0x37, 0x500000, 3, AD7124_RW}, /* AD7124_Gain_6 */
	{0x38, 0x500000, 3, AD7124_RW}, /* AD7124_Gain_7 */
};
/*! AD7124 registers list*/
enum ad7124_registers 
{
	AD7124_Status = 0x00,
	AD7124_ADC_CONTROL,
	AD7124_Data,
	AD7124_IOCONTROL_1,
	AD7124_IOCONTROL_2,
	AD7124_ID,
	AD7124_Error,
	AD7124_ERROR_EN,
	AD7124_MCLK_COUNT,
	AD7124_CHANNEL_0,
	AD7124_CHANNEL_1,
	AD7124_CHANNEL_2,
	AD7124_CHANNEL_3,
	AD7124_CHANNEL_4,
	AD7124_CHANNEL_5,
	AD7124_CHANNEL_6,
	AD7124_CHANNEL_7,
	AD7124_CHANNEL_8,
	AD7124_CHANNEL_9,
	AD7124_CHANNEL_10,
	AD7124_CHANNEL_11,
	AD7124_CHANNEL_12,
	AD7124_CHANNEL_13,
	AD7124_CHANNEL_14,
	AD7124_CHANNEL_15,
	AD7124_CONFIG_0,
	AD7124_CONFIG_1,
	AD7124_CONFIG_2,
	AD7124_CONFIG_3,
	AD7124_CONFIG_4,
	AD7124_CONFIG_5,
	AD7124_CONFIG_6,
	AD7124_CONFIG_7,
	AD7124_FILTER_0,
	AD7124_FILTER_1,
	AD7124_FILTER_2,
	AD7124_FILTER_3,
	AD7124_FILTER_4,
	AD7124_FILTER_5,
	AD7124_FILTER_6,
	AD7124_FILTER_7,
	AD7124_OFFSET_0,
	AD7124_OFFSET_1,
	AD7124_OFFSET_2,
	AD7124_OFFSET_3,
	AD7124_OFFSET_4,
	AD7124_OFFSET_5,
	AD7124_OFFSET_6,
	AD7124_OFFSET_7,
	AD7124_GAIN_0,
	AD7124_GAIN_1,
	AD7124_GAIN_2,
	AD7124_GAIN_3,
	AD7124_GAIN_4,
	AD7124_GAIN_5,
	AD7124_GAIN_6,
	AD7124_GAIN_7,
	AD7124_REG_END
};
#endif /* __AD7124_H__ */

#18 华芯微特 » 基于华芯微特SWM320的SSD1306显示器的驱动开发--缥缈九哥 » 2020-05-09 21:55:24

缥缈九哥
回复: 0
/********************************************************************************/
/* @file	ssd1306.c															*/
/* @version	V1.00																*/
/* $author:	yuanxihua@21cn.com													*/
/* $Date: 	2018/11/27 23:39p $ 												*/
/* @brief 	SWM320RBT6 Series SSD1306 Driver Sample Code						*/
/*																				*/
/* @note																		*/
/* Copyright (C) 2010-2019 PM9GZY Technology Corp. All rights reserved.			*/
/*																				*/
/********************************************************************************/ 
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "dotcode.h"
/*
_________________________________________________
|	SWM320RBT6						SSD1306		|
|												|
|	PB0		PDN			---->		PDN			|
|	PP9		LRST		---->		RST			|
|	PP8		NSS0		---->		SCS			|
|	PP7		MISO0		<----		SDC			|
|	PP6		MOSI0		---->		SDA			|
|	PP5		SCLK0		---->		SCK			|
|_______________________________________________|
*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define SSD1306_CMD()		GPIO_ClrBit(GPIOP, PIN7)
#define SSD1306_DAT()		GPIO_SetBit(GPIOP, PIN7)
#define SSD1306_PON()		GPIO_ClrBit(GPIOB, PIN0)
#define SSD1306_OFF()		GPIO_SetBit(GPIOB, PIN0)
#define SSD1306_RST()		GPIO_ClrBit(GPIOP, PIN9)
#define SSD1306_NST()		GPIO_SetBit(GPIOP, PIN9)
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
void SPI0Init(void)
{
	SPI_InitStructure SPI_initStruct;

	GPIO_Init(GPIOB, PIN0, 1, 0, 0);
	GPIO_Init(GPIOP, PIN9, 1, 0, 0);
	
	PORT_Init(PORTP, PIN5 , FUNMUX1_SPI0_SCLK, 0);
	PORT_Init(PORTP, PIN6 , FUNMUX0_SPI0_MOSI, 0);
	GPIO_Init(GPIOP, PIN7, 1, 0, 0);//FUNMUX1_SPI0_MISO
	PORT_Init(PORTP, PIN8, FUNMUX0_SPI0_SSEL, 0);
	
	SPI_initStruct.clkDiv = SPI_CLKDIV_4;//0.04US
//	SPI_initStruct.clkDiv = SPI_CLKDIV_8;//0.07US
//	SPI_initStruct.clkDiv = SPI_CLKDIV_16;//0.14US
//	SPI_initStruct.clkDiv = SPI_CLKDIV_32;//0.26US
//	SPI_initStruct.clkDiv = SPI_CLKDIV_64;//0.53S
//	SPI_initStruct.clkDiv = SPI_CLKDIV_128;//1.07US
//	SPI_initStruct.clkDiv = SPI_CLKDIV_256;//2.14US
//	SPI_initStruct.clkDiv = SPI_CLKDIV_512;//4.28US
	SPI_initStruct.FrameFormat = SPI_FORMAT_SPI;
	SPI_initStruct.SampleEdge = SPI_FIRST_EDGE;
	SPI_initStruct.IdleLevel = SPI_LOW_LEVEL;
	SPI_initStruct.WordSize = 8;
	SPI_initStruct.Master = 1;
	SPI_initStruct.RXHFullIEn = 0;
	SPI_initStruct.TXEmptyIEn = 0;
	SPI_initStruct.TXCompleteIEn = 0;
	SPI_Init(SPI0, &SPI_initStruct);
	
	SPI_Open(SPI0);
}
void SSD1306_WriteCMD(uint8_t cmd)
{
	SSD1306_CMD();
	uint8_t r=SPI_ReadWrite(SPI0,cmd);
}
void SSD1306_WriteDAT(uint8_t dat)
{
	SSD1306_DAT();
	uint8_t r=SPI_ReadWrite(SPI0,dat);
}
void OLED_Init(void)
{
	SPI0Init();
	SSD1306_OFF();
	osDelay(100);
	SSD1306_PON();
	SSD1306_RST();
	osDelay(100);
	SSD1306_NST();
	osDelay(200);	//这里的延时很重要
	
	SSD1306_WriteCMD(0xAE); //display off
	SSD1306_WriteCMD(0x20);	//Set Memory Addressing Mode	
	SSD1306_WriteCMD(0x10);	//00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid
	SSD1306_WriteCMD(0xb0);	//Set Page Start Address for Page Addressing Mode,0-7
	SSD1306_WriteCMD(0xc8);	//Set COM Output Scan Direction
	SSD1306_WriteCMD(0x00); //---set low column address
	SSD1306_WriteCMD(0x10); //---set high column address
	SSD1306_WriteCMD(0x40); //--set start line address
	SSD1306_WriteCMD(0x81); //--set contrast control register
	SSD1306_WriteCMD(0xff); //亮度调节 0x00~0xff
	SSD1306_WriteCMD(0xa1); //--set segment re-map 0 to 127
	SSD1306_WriteCMD(0xa6); //--set normal display
	SSD1306_WriteCMD(0xa8); //--set multiplex ratio(1 to 64)
	SSD1306_WriteCMD(0x3F); //
	SSD1306_WriteCMD(0xa4); //0xa4,Output follows RAM content;0xa5,Output ignores RAM content
	SSD1306_WriteCMD(0xd3); //-set display offset
	SSD1306_WriteCMD(0x00); //-not offset
	SSD1306_WriteCMD(0xd5); //--set display clock divide ratio/oscillator frequency
	SSD1306_WriteCMD(0xf0); //--set divide ratio
	SSD1306_WriteCMD(0xd9); //--set pre-charge period
	SSD1306_WriteCMD(0x22); //
	SSD1306_WriteCMD(0xda); //--set com pins hardware configuration
	SSD1306_WriteCMD(0x12);
	SSD1306_WriteCMD(0xdb); //--set vcomh
	SSD1306_WriteCMD(0x20); //0x20,0.77xVcc
	SSD1306_WriteCMD(0x8d); //--set DC-DC enable
	SSD1306_WriteCMD(0x14); //
	SSD1306_WriteCMD(0xaf); //--turn on oled panel
}

void OLED_Origin(unsigned char x, unsigned char y) //设置起始点坐标
{ 
	SSD1306_WriteCMD(0xb0+y);
	SSD1306_WriteCMD(((x&0xf0)>>4)|0x10);
	SSD1306_WriteCMD((x&0x0f)|0x01);
}
void OLED_Wakeup(void)			//将OLED从休眠中唤醒
{
	SSD1306_WriteCMD(0X8D);  	//设置电荷泵
	SSD1306_WriteCMD(0X14);  	//开启电荷泵
	SSD1306_WriteCMD(0XAF);  	//OLED唤醒
}

void OLED_Sleep(void)			//让OLED休眠 -- 休眠模式下,OLED功耗不到10uA
{
	SSD1306_WriteCMD(0X8D);  	//设置电荷泵
	SSD1306_WriteCMD(0X10);  	//关闭电荷泵
	SSD1306_WriteCMD(0XAE);  	//OLED休眠
}
void OLED_Fill(uint8_t data)	//全屏填充
{
	unsigned char m,n;
	for(m=0;m<8;m++)
	{
		SSD1306_WriteCMD(0xb0+m);	//page0-page1
		SSD1306_WriteCMD(0x00);		//low column start address
		SSD1306_WriteCMD(0x10);		//high column start address
		for(n=0;n<128;n++)
		{
			SSD1306_WriteDAT(data);
		}
	}
}
//--------------------------------------------------------------
// Prototype      : void OLED_ShowChar(unsigned char x, unsigned char y, unsigned char ch[], unsigned char TextSize)
// Calls          : 
// Parameters     : x,y -- 起始点坐标(x:0~127, y:0~7); ch[] -- 要显示的字符串; TextSize -- 字符大小(1:6*8 ; 2:8*16)
// Description    : 显示codetab.h中的ASCII字符,有6*8和8*16可选择
//--------------------------------------------------------------
void OLED_ShowStr(unsigned char x, unsigned char y, unsigned char ch[], unsigned char TextSize)
{
	unsigned char c = 0,i = 0,j = 0;
	switch(TextSize)
	{
		case 1:
		{
			while(ch[j] != '\0')
			{
				c = ch[j] - 32;
				if(x > 126)
				{
					x = 0;
					y++;
				}
				OLED_Origin(x,y);
				for(i=0;i<6;i++){SSD1306_WriteDAT(F6x8[c][i]);}
				x += 6;
				j++;
			}
		}break;
		case 2:
		{
			while(ch[j] != '\0')
			{
				c = ch[j] - 32;
				if(x > 120)
				{
					x = 0;
					y++;
				}
				OLED_Origin(x,y);
				for(i=0;i<8;i++)
					SSD1306_WriteDAT(F8X16[c*16+i]);
				OLED_Origin(x,y+1);
				for(i=0;i<8;i++)
					SSD1306_WriteDAT(F8X16[c*16+i+8]);
				x += 8;
				j++;
			}
		}break;
	}
}

//--------------------------------------------------------------
// Prototype      : void OLED_ShowCN(unsigned char x, unsigned char y, unsigned char N)
// Calls          : 
// Parameters     : x,y -- 起始点坐标(x:0~127, y:0~7); N:汉字在codetab.h中的索引
// Description    : 显示codetab.h中的汉字,16*16点阵
//--------------------------------------------------------------
void OLED_ShowCN(unsigned char x, unsigned char y, unsigned char N)
{
	unsigned char wm=0;
	unsigned int  adder=32*N;
	OLED_Origin(x,y+0);for(wm=0;wm<16;wm++){SSD1306_WriteDAT(F16x16[adder++]);}
	OLED_Origin(x,y+1);for(wm=0;wm<16;wm++){SSD1306_WriteDAT(F16x16[adder++]);}
}

//--------------------------------------------------------------
// Prototype      : void OLED_DrawBMP(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,unsigned char BMP[]);
// Calls          : 
// Parameters     : x0,y0 -- 起始点坐标(x0:0~127, y0:0~7); x1,y1 -- 起点对角线(结束点)的坐标(x1:1~128,y1:1~8)
// Description    : 显示BMP位图
//--------------------------------------------------------------
void OLED_DrawBMP(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,unsigned char BMP[])
{
	unsigned int j=0;
	unsigned char x,y;

	if(y1%8==0){y = y1/8;}else{y = y1/8 + 1;}
	for(y=y0;y<y1;y++)
	{
		OLED_Origin(x0,y);
		for(x=x0;x<x1;x++){SSD1306_WriteDAT(BMP[j++]);}
	}
}

void OLED_Welcome(void)
{
	uint32_t i;
	OLED_Init();
	{
//		OLED_Fill(0xFF);//全屏点亮
//		osDelay(100);
		OLED_Fill(0x00);//全屏灭
//		osDelay(500);
		for(i=0;i<4;i++)
		{
			OLED_ShowCN(32+i*16,0,i);//测试显示中文
		}
//		osDelay(2000);
		OLED_ShowStr(40,3,"PM9GZY",2);		//测试8*16字符
		OLED_ShowStr(13,5,"yuanxihua@139.com",1);		//测试6*8 字符
		osDelay(1000);
//		OLED_Fill(0);//清屏
//		OLED_DrawBMP(0,0,128,8,(unsigned char *)BMP1);//测试BMP位图显示
//		osDelay(1000);
	}
}
void SSD1306_Test(void)
{
//	uint32_t i;
//	while(1)
//	{
//		SSD1306_WriteCMD(0x55);
//		SSD1306_WriteDAT(0xAA);
//	}
	OLED_Init();
	OLED_Fill(0xff);
	osDelay(100);
	
}

void OLED_Volute(float *vol)
{
	unsigned char buf[20];

	OLED_Fill(0x00);//全屏灭
	for(int i=0;i<4;i++){OLED_ShowCN(32+i*16,0,i);}//测试显示中文
	sprintf((char *)buf,"CH1: %3.10f V",vol[0]);OLED_ShowStr(0,3,buf,1);
	sprintf((char *)buf,"CH2: %3.10f V",vol[1]);OLED_ShowStr(0,4,buf,1);
	sprintf((char *)buf,"CH3: %3.10f V",vol[2]);OLED_ShowStr(0,5,buf,1);
	sprintf((char *)buf,"CH4: %3.10f V",vol[3]);OLED_ShowStr(0,6,buf,1);
}

void OLED_Battery(uint16_t bat)
{
	uint16_t x=122-((36*bat)/100);if(x>122){x=122;}if(x<86){x=86;}
	char str[10];sprintf(str,"%d%%",bat);
	OLED_ShowStr(10,0,(unsigned char*)str,2);		//测试8*16字符
	OLED_Origin(79 ,0);for(int i=79 ;i<82 ;i++){SSD1306_WriteDAT(0xE0);}
	OLED_Origin(79 ,1);for(int i=79 ;i<82 ;i++){SSD1306_WriteDAT(0x07);}
	OLED_Origin(82 ,0);for(int i=82 ;i<84 ;i++){SSD1306_WriteDAT(0xff);}
	OLED_Origin(82 ,1);for(int i=82 ;i<84 ;i++){SSD1306_WriteDAT(0xff);}
	OLED_Origin(84 ,0);for(int i=84 ;i<86 ;i++){SSD1306_WriteDAT(0x03);}
	OLED_Origin(84 ,1);for(int i=84 ;i<86 ;i++){SSD1306_WriteDAT(0xC0);}
	OLED_Origin(86 ,0);for(int i=86 ;i<123;i++){SSD1306_WriteDAT((i>=x)?0xF3:0x03);}
	OLED_Origin(86 ,1);for(int i=86 ;i<123;i++){SSD1306_WriteDAT((i>=x)?0xCF:0xC0);}
	OLED_Origin(123,0);for(int i=123;i<125;i++){SSD1306_WriteDAT(0x03);}
	OLED_Origin(123,1);for(int i=123;i<125;i++){SSD1306_WriteDAT(0xC0);}
	OLED_Origin(125,0);for(int i=125;i<127;i++){SSD1306_WriteDAT(0xff);}
	OLED_Origin(125,1);for(int i=125;i<127;i++){SSD1306_WriteDAT(0xff);}
}
void OLED_Digital(unsigned char x, unsigned char y, unsigned char N)
{
	unsigned char wm=0;unsigned int  adder=64*N;
	OLED_Origin(x,y+0);for(wm=0;wm<16;wm++){SSD1306_WriteDAT(F32X32[adder++]);}
	OLED_Origin(x,y+1);for(wm=0;wm<16;wm++){SSD1306_WriteDAT(F32X32[adder++]);}
	OLED_Origin(x,y+2);for(wm=0;wm<16;wm++){SSD1306_WriteDAT(F32X32[adder++]);}
	OLED_Origin(x,y+3);for(wm=0;wm<16;wm++){SSD1306_WriteDAT(F32X32[adder++]);}
}
void OLED_pCHz(uint16_t bat,uint32_t pchz,uint8_t PC)
{
	OLED_Fill(0x00);//全屏灭
	OLED_Battery(bat);
	if(pchz>999){OLED_Digital(20,2, pchz/1000);pchz%=1000;
	if(pchz<100){OLED_Digital(40,2, 0);}if(pchz<10){OLED_Digital(60,2, 0);}}
	if(pchz>99 ){OLED_Digital(40,2, pchz/100 );pchz%=100;
	if(pchz<10 ){OLED_Digital(60,2, 0);}}
	if(pchz>9  ){OLED_Digital(60,2, pchz/10  );pchz%=10 ;}
	OLED_Digital(80,2, pchz);
	
	if(PC){OLED_ShowStr(108,7,"p",1);OLED_ShowStr(116,6,"C",2);}
	else  {OLED_ShowStr(108,6,"H",2);OLED_ShowStr(116,7,"z",1);}	
}

#19 VMWare/Linux/Ubuntu/Fedora/CentOS/U-BOOT » 基于9GSAM9260EK开发板的arm-linux开发过程 » 2020-05-09 21:18:03

缥缈九哥
回复: 1

一,准备VMWARE+LINUX安装软件包

1,在http://www.ubuntu.com/getubuntu/download
    下载Ubuntu 7.10的X86桌面版本的ISO文件:
    http://mirror.rootguide.org/ubuntu-releases/gutsy/ubuntu-7.10-desktop-i386.iso
1,在http://releases.ubuntu.com/releases/.pool/
    下载Ubuntu 7.10的X86桌面版本的ISO文件:
    ubuntu-7.10-desktop-i386.iso
2,在http://www.crsky.com/soft/8612.html
    下载VMware Workstation v5.5.3 Build 34685 及 汉化补丁
    VMware-workstation-5.5.3-34685.rar
    VMware_Workstation_5.5.3_34685H.rar
2,在http://www.crsky.com/soft/1863.html
    下载VMware Workstation v6.0.0 Build 45731 及 汉化补丁
    VMwareWorkstation-v6.0.0.45731.rar
    VMwareWorkstation_v60045731H.rar
3,在http://www.crsky.com/soft/6748.html上
    下载SecureCRT v5.5.2
    SecureCRT-v5.5.2.rar
3,在http://www.crsky.com/soft/6838.html
    下载SecureCRT v5.1.2 Build 274 汉化版 by 偃月青龙
    SecureCRT_5.1.2H.rar
3,在http://www.crsky.com/soft/6838.html   
    SecureCRT v5.1.3 Build 281 汉化版
    HAP_SecureCRT_5.1.3.rar
4,在http://www.codesourcery.com/gnu_toolchains/arm/download.html
    下载ARM EABI + IA32 GNU/Linux 开发工具
    arm-2007q3-53-arm-none-eabi-i686-pc-linux-gnu.tar.bz2
    下载ARM GNU/Linux + IA32 GNU/Linux 开发工具
    arm-2007q3-51-arm-none-gnueabi-i686-pc-linux-gnu.tar.bz2
4,在ftp://ftp.denx.de/pub/eldk/4.1/
    下载arm-linux-x86-uclibc
    ftp://ftp.denx.de/pub/eldk/4.1/arm-linux-x86-uclibc/iso/arm-2007-01-22-uclibc.iso       
    下载arm-linux-x86
    ftp://ftp.denx.de/pub/eldk/4.1/arm-linux-x86/iso/arm-2007-01-21.iso

二,准备AT91SAM9260+LINUX开发包

1,在http://www.atmel.com/dyn/products/tools_card.asp?tool_id=3933
    下载AT91SAM9260-EK 全套资料
    软件及硬件文档
1,在http://www.atmel.com/dyn/products/tools_card.asp?tool_id=3883
    下载AT91-ISP.exe及使用手册
    Install AT91-ISP v1.10.exe
    doc6224.pdf     doc6272.pdf     doc6132.pdf
2,在http://www.atmel.com/dyn/products/tools_card.asp?tool_id=4093
    下载AT91 Bootstrap及使用手册
    AT91Bootstrap1.5.zip
    doc6277.pdf
3,在http://sourceforge.net/projects/u-boot
    下载Das U-Boot - Universal Bootloader   
    u-boot-1.1.5.tar.bz2
    u-boot-1.1.6.tar.bz2
3,在ftp://ftp.denx.de/pub/u-boot/
    下载U-Boot-1.1.5 released
    u-boot-1.1.5.tar.bz2
4,在http://www.at91.com/ 上注册
    下载u-boot-1.1.5补丁
    u-boot-1.1.5_atmel_1.4.diff.bz2
5,在http://www.kernel.org/pub/linux/kernel/v2.6/
    下载Linux 2.6 内核源码
    linux-2.6.23.tar.bz2
6,在http://maxim.org.za/AT91RM9200/2.6/
    下载Linux 2.6 Patches
    2.6.23-at91.patch.gz
7,在http://www.busybox.net/
    下载BusyBox 1.8.2. (svn, patches, how to add a patch)
    busybox-1.8.2.tar.bz2

三,安装VMWARE+LINUX开发平台

1,在XP系统上安装VMwareWorkstation-v6.0.0.45731及汉化补丁
    A,双击VMware Workstation v6.0 Build 45731 KeyGen.exe 启动破解程序,“serial”栏目中会产生一个安装
        用的序列号,"Type"栏需要为“VMware Workstation ACE Edition for Windows V6";
    B,双击VMware-workstation-6.0.0-45731.exe 启动安装,点击NEXT,选择Typical;再NEXT,安装文件夹选择
        默认;再NEXT,快捷方式产生用默认;再NEXT,按install;输入使用者,公司和序列号,最后点击finish完成
        安装,重启动电脑;
    C,双击setup_tracky.exe 启动汉化,点击“下一步”,勾选“同意许可”;再“下一步”又“下一步”,安装
        文件夹选择默认;再“下一步”再“下一步”,去掉第三方插件;再“下一步”后,点击“安装”;最后点击
        “完成”;
    注意:XP系统需要512MB以上内存,15GB以上硬盘空间。
   
2,在VMware Workstation上安装ubuntu-7.10-desktop的X86版本
    A,双击桌面VMware Workstation图标进入虚拟机,点击“新建虚拟机”启动建立向导;点“下一步”选择“典型”;
        点“下一步”选择操作系统为“linux"和版本为“Ubuntu";点“下一步”输入虚拟机名称和选择安装路径;点
        “下一步”选择“使用桥接网络”;“下一步”磁盘大小填15GB以上,勾选“分割磁盘为2GB文件”;点击“完成”;
    B,进入建立好的虚拟机页面,双击“CD-ROM”,“连接”选择“使用ISO镜像”; 点击“浏览”选择下载的“ubuntu-
        7.10-desktop-i386.iso”文件“打开”并“确定”;点击虚拟机页面中“命令”中的“启动该虚拟机”启动安装;
    C,在LINUX安装界面中按F2功能键,选择“中文(简体)”;用上下箭头选择高亮“启动或安装UBUNTU”时按回车;进入
        Ubuntu-7.10-desktop的X86版本的LiveCD界面,双击“安装”进入了LiveCD安装到硬盘的过程;
    D,在安装界面点击“前进”,地点用默认“上海”;点击“前进”,键盘布局用默认“美国”;点击“前进”硬盘分区
        用默认“向导”,点击“前进”,输入用户名和密码;点击“前进”,在准备安装中,点击“Install";安装完成
        后,点击“现在重启”并把虚拟机“设置”中的“CD-ROM”改回“使用物理驱动器”;
       
    注意:XP系统需在DHCP的局域网内,要独立分配IP给虚拟机;安装的用户名和密码区别于ROOT用户,每次登陆系统及修改
        系统配置都要用到,需要牢记。

四,配置并更新ubuntu桌面系统

1,启动根用户和配置网络
A,进入系统后在启动菜单“应用程序”->“附件”->“终端”拉到桌面上;把启动菜单“位置”中的“计算机”也
        拉到桌面上;双击桌面“终端”中打开命令行终端
B,启用root用户并修改密码
        yuanxh@yuanxh-desktop:~$ sudo passwd root
C,进入root用户操作
        yuanxh@yuanxh-desktop:~$ su
D,查看本机IP配置信息
        root@yuanxh-desktop:/home/yuanxh# ifconfig -a
E,在启动菜单“系统”->“系统管理”->“网络”中
  填入IP,子域掩码,网关,DNS等网络参数;
F,修改.bashrc启用ll la等到命令转义
  root@yuanxh-desktop:/home/yuanxh# vi /root/.bashrc
 
2,安装虚拟驱动Vmware tools
A,进入系统后在虚拟机菜单“虚拟机”中点击“安装Vmware tools”后桌面会弹出一个CD-ROM内容的文件夹,里面有两个
  rpm和tar.gz压缩文件包;
B,双击桌面“终端”打开命令行终端,用命令模式安装虚拟驱动:
  切换到root用户
            yuanxh@yuanxh-desktop:~$ su
        建立文件夹
            root@yuanxh-desktop:/home/yuanxh# mkdir vm-tools
        修改文件夹权限
            root@yuanxh-desktop:/home/yuanxh# chmod 777 vm-tools/
        进入文件夹
            root@yuanxh-desktop:/home/yuanxh# cd vm-tools/
        复制虚拟驱动软件包
            root@yuanxh-desktop:/home/yuanxh/vm-tools# cp /media/cdrom0/VMwareTools-6.0.0-45731.tar.gz .
        解压虚拟驱动文件包
            root@yuanxh-desktop:/home/yuanxh/vm-tools# tar xzvf VMwareTools-6.0.0-45731.tar.gz
        进入虚拟驱动文件夹
            root@yuanxh-desktop:/home/yuanxh/vm-tools# cd vmware-tools-distrib/
        运行虚拟驱动安装脚本
            root@yuanxh-desktop:/home/yuanxh/vm-tools/vmware-tools-distrib# ./vmware-install.pl
C,一路按回车键,直到最后能选择屏幕分辨率大小,并且鼠标能自由进入虚拟机和XP之间;

3,启用XP与虚拟机系统间的共享文件夹功能
A,在虚拟机菜单“虚拟机”->“设置”中,切换到“选项”页;选择到“共享文件夹” 设置,选择“总是启用”;点击文件夹
  下的添加进入“添加文件夹向导”;点击“下一步”设置文件夹“名称”和选择XP系统中的文件夹;点击“下一步”配置好
  共享文件夹属性后,点击“完成”;退出向导,点击“确定”退出设置;
B,在设置好共享文件夹后,并且安装好虚拟驱动后启动虚拟机,便可以在虚拟机中看到共享文件夹的内容;
     root@yuanxh-desktop:/home/yuanxh# ls -l  /mnt/hgfs
       
4,更新软件包服务器源后更新升级系统并安装SSH和ZMODEM协议
A,在http://www.ubuntu-nl.org/source-o-matic/
  自动产生source.list内容,更新到/etc/apt/sources.list 中;
B,切换到root用户后执行以下命令更新升级系统:
  网络更新系统
        root@yuanxh-desktop:/home/yuanxh# apt-get update
        网络升级系统
        root@yuanxh-desktop:/home/yuanxh# apt-get upgrade
    C,网络安装系统汉字库
        root@yuanxh-desktop:/home/yuanxh# apt-get install language-pack-zh language-pack-zh-base language-support-zh
        在系统登陆界面的“选项”中可以选择系统默认语言;在启动菜单的“系统”->“系统管理”->“语言支持”中也可以
        修改系统默认语言支持;
    D,网络安装SSH客户端和服务器端
        root@yuanxh-desktop:/home/yuanxh# apt-get install ssh openssh-server
        只有安装了这个才能用SecureCRT远程终端SSH访问系统
    E,用以下命令查找并安装ZMMODEM协议支持软件包:
        查找rzsz相关软件包
        root@yuanxh-desktop:~# apt-cache search rzsz
        显示lrzsz软件包详细情况
     root@yuanxh-desktop:~# apt-cache show lrzsz       
        网络安装zmodem传输协议
        root@yuanxh-desktop:/home/yuanxh# apt-get install lrzsz
        查看网络下载软件包存放目录
        root@yuanxh-desktop:/home/yuanxh# ll /var/cache/apt/archives/

5,安装SecureCRT远程终端SSH访问虚拟机和启用SFTP文件传输功能
A,双击HAP_SecureCRT_5.1.3.exe,点击“继续”;选择“接受协议”,再点击“继续”;点击“继续”后安装路径
     选择默认的;点击“继续”后选择“完整安装”;点击“继续”后产生快捷方式用默认;点击“安装”后点击“完成”;
B,双击桌面SecureCRT 5.1.3图标启动终端软件,在输入许可数据中依次输入“名字”“公司”“序列号”“许可密钥”和
  “发布日期”完成注册;
C,利用向导建立一个SSH会话到虚拟机;“下一步”后输入虚拟机IP地址和登陆用户名,建立好后双击会话SSH登陆LINUX,
  在会话属性中可配置终端类型,字体,滚屏行数,字符编码,XMODEM和SFTP默认路径等;
D,建立了到LINUX的SSH会话后,在SecureCRT 5.1.3界面的菜单“文件”->“连接SFTP标签”可启动到相应的LINUX的SFTP连接,
  在SFTP标签中输入“help”可以查看相关的SFTP命令。

五,建立FTP,NFS和交叉编译环境

1,用命令配置TFTP服务
    A, 建立TFTP系统根目录并修改权限
        root@yuanxh-desktop:/home/yuanxh/at91_works# mkdir  /tftpboot
        root@yuanxh-desktop:/home/yuanxh/at91_works# chmod 777  /tftpboot
    B,安装TFTP服务器端和客户端
        root@yuanxh-desktop:/# sudo apt-get install tftp tftpd openbsd-inetd
    C,修改配置文件使用TFTP根目录
        root@yuanxh-desktop:/home/yuanxh/at91_works# vi  /etc/inetd.conf
        在/etc/inetd.conf新行中填入以下内容
        tftp    dgram   udp     wait    nobody  /usr/sbin/tcpd /usr/sbin/in.tftpd /tftpboot
    D,启动服务
        root@yuanxh-desktop:/home/yuanxh/at91_works#  /etc/init.d/openbsd-inetd  restart
    E,测试服务
        root@yuanxh-desktop:/home/yuanxh# touch /tftpboot/aaa
        root@yuanxh-desktop:/home/yuanxh# vi /tftpboot/aaa
        root@yuanxh-desktop:/home/yuanxh# tftp 192.168.1.100
        tftp> get aaa
        tftp> quit
        root@yuanxh-desktop:/home/yuanxh# cat aaa

2,用命令配置NFS服务
    A,安装NFS服务器端
        root@yuanxh-desktop:/home/yuanxh# apt-get install nfs-kernel-server  nfs-common  portmap
    B,配置访问目录及权限
        root@yuanxh-desktop:/home/yuanxh/at91_works# mkdir  /nfsboot
        root@yuanxh-desktop:/home/yuanxh/at91_works# chmod 777  /nfsboot
        root@yuanxh-desktop:/home/yuanxh/at91_works# touch  /nfsboot/yuanxh
        root@yuanxh-desktop:/# vi /etc/exports
        在/etc/exports新行中填入以下内容
        /nfsboot  192.168.1.0/24(rw,sync)
    C,启动服务
        root@yuanxh-desktop:/# exportfs -ra
        root@yuanxh-desktop:/# /etc/init.d/portmap restart
        root@yuanxh-desktop:/# /etc/init.d/nfs-common restart
        root@yuanxh-desktop:/# /etc/init.d/nfs-kernel-server restart
    D,测试服务
        root@yuanxh-desktop:/# mount 192.168.1.100:/nfsboot  /mnt
        root@yuanxh-desktop:/home/yuanxh# ll /mnt
        root@yuanxh-desktop:/home/yuanxh# rm -rf /mnt/yuanxh
        root@yuanxh-desktop:/home/yuanxh# showmount
        root@yuanxh-desktop:/home/yuanxh# df
        root@yuanxh-desktop:/home/yuanxh# umount /mnt
        root@yuanxh-desktop:/home/yuanxh# ll /nfsboot
       
3,安装交叉编译工具链
    A,利用SecureCRT 5.1.3登陆,传送文件到系统
        root@yuanxh-desktop:/home/yuanxh# mkdir /usr/local/arm
        root@yuanxh-desktop:/home/yuanxh# chmod 777 /usr/local/arm/
        root@yuanxh-desktop:/home/yuanxh# cd /usr/local/arm/
        root@yuanxh-desktop:/usr/local/arm# rz
        在SecureCRT弹出的窗口中选择交叉编译工具安装包
    B,解压交叉编译工具包
        root@yuanxh-desktop:/usr/local/arm# tar xjvf arm-2007q3-51-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2
        root@yuanxh-desktop:/usr/local/arm# tar xjvf arm-2007q3-53-arm-none-eabi-i686-pc-linux-gnu.tar.bz2
    C,安装ELDK交叉编译工具
        在虚拟机窗口中右击“arm-2007-01-22-uclibc.iso”选择“解压到此处”来解压;
        root@yuanxh-desktop:/usr/local/arm# cd arm-2007-01-22-uclibc/
        root@yuanxh-desktop:/usr/local/arm/arm-2007-01-22-uclibc# chmod 777 install
        root@yuanxh-desktop:/usr/local/arm/arm-2007-01-22-uclibc# ./install -d /usr/local/arm/eldk-uclibc-4.1
        在虚拟机窗口中右击“arm-2007-01-21.iso”选择“解压到此处”来解压;
        root@yuanxh-desktop:/usr/local/arm# cd arm-2007-01-21/
        root@yuanxh-desktop:/usr/local/arm/arm-2007-01-21# chmod 777 install
        root@yuanxh-desktop:/usr/local/arm/arm-2007-01-21# ./install -d /usr/local/arm/eldk-4.1
    D,把编译器路径添加到系统路径中
        root@yuanxh-desktop:/usr/local/arm#  vi /root/.bashrc
        在alias l='ls -CF'后的空白处填上:
  PATH=$PATH:/usr/local/arm/eldk-4.1/usr/bin:/usr/local/arm/eldk-4.1/bin
  export PATH
  启动新系统路径
  root@yuanxh-desktop:/usr/local/arm# source /root/.bashrc
  显示新系统路径
  root@yuanxh-desktop:/usr/local/arm# echo $PATH
  查看版本号
  root@yuanxh-desktop:/usr/local/arm# arm-linux-gcc -v
    E,查看交叉编译工具版本信息
        root@yuanxh-desktop:/usr/local/arm# ./arm-2007q3/bin/arm-none-eabi-gcc -v
        root@yuanxh-desktop:/usr/local/arm# ./arm-2007q3/bin/arm-none-linux-gnueabi-gcc -v
        root@yuanxh-desktop:/usr/local/arm# ./eldk-uclibc-4.1/usr/bin/arm-linux-gcc -v

六,编译Bootstrap+U-BOOT启动代码 

1,传送文件包到LINUX系统并解压
    A,利用SecureCRT 5.1.3登陆,传送文件到系统
        root@yuanxh-desktop:/home/yuanxh# mkdir at91_works
        root@yuanxh-desktop:/home/yuanxh# chmod 777 at91_works/
        root@yuanxh-desktop:/home/yuanxh# cd at91_works/
        root@yuanxh-desktop:/home/yuanxh/at91_works# rz
        在SecureCRT弹出的窗口中选择AT91Bootstrap1.5.zip,u-boot-1.1.5.tar.bz2,u-boot-1.1.5_atmel_1.4.diff.bz2软件包
    B,解压所有软件包
        在虚拟机窗口中右击AT91Bootstrap1.5.zip,选择“解压到此处”来解压,同样解压u-boot-1.1.5_atmel_1.4.diff.bz2;
        root@yuanxh-desktop:/home/yuanxh/at91_works# tar xjvf u-boot-1.1.5.tar.bz2
       
2,编译生成一级启动目标码
    A,为Bootstrap-v1.5指定编译器
        root@yuanxh-desktop:/home/yuanxh/at91_works# cd Bootstrap-v1.5/board/at91sam9260ek/nandflash/
        root@yuanxh-desktop:/home/yuanxh/at91_works/Bootstrap-v1.5/board/at91sam9260ek/nandflash# vi Makefile
        把文件中的CROSS_COMPILE=/usr/local/arm/eldk-4.1/usr/bin/arm-linux-填好,指定eldk-4.1的编译器;
    B,编译生成了目标码并传送回XP
        root@yuanxh-desktop:/home/yuanxh/at91_works/Bootstrap-v1.5/board/at91sam9260ek/nandflash# make
        root@yuanxh-desktop:/home/yuanxh/at91_works/Bootstrap-v1.5/board/at91sam9260ek/nandflash# sz nandflash_at91sam9260ek.bin
        在dataflash目录同样修改Makefile也能生成dataflash_at91sam9260ek.bin;
        注意:必须保证 dataflash_at91sam9260ek.bin 和平nandflash_at91sam9260ek.bin 小于4KB;
3,编译生成二级启动目标码
    A,打上补丁
        root@yuanxh-desktop:/home/yuanxh/at91_works# cd u-boot-1.1.5
        root@yuanxh-desktop:/home/yuanxh/at91_works/u-boot-1.1.5# mv ../u-boot-1.1.5_atmel_1.4.diff .
        root@yuanxh-desktop:/home/yuanxh/at91_works/u-boot-1.1.5# apt-get install patch
        root@yuanxh-desktop:/home/yuanxh/at91_works/u-boot-1.1.5# patch -p1 < ./u-boot-1.1.5_atmel_1.4.diff
    B,指定编译器
        root@yuanxh-desktop:/home/yuanxh/at91_works/u-boot-1.1.5# vi Makefile
        把CROSS_COMPILE = arm-linux- 改成 CROSS_COMPILE=/usr/local/arm/eldk-4.1/usr/bin/arm-linux-
    C,配置并编译在DATAFLASH中运行模式
        root@yuanxh-desktop:/home/yuanxh/at91_works/u-boot-1.1.5# apt-get install libncurses5-dev
        root@yuanxh-desktop:/home/yuanxh/at91_works/u-boot-1.1.5# make clean
        root@yuanxh-desktop:/home/yuanxh/at91_works/u-boot-1.1.5# make mrproper
        root@yuanxh-desktop:/home/yuanxh/at91_works/u-boot-1.1.5# make at91sam9260ek_config
        root@yuanxh-desktop:/home/yuanxh/at91_works/u-boot-1.1.5# make
        root@yuanxh-desktop:/home/yuanxh/at91_works/u-boot-1.1.5# mv u-boot.bin u-boot-env-df.bin
        注意:需要修改一下/u-boot-1.1.5/examples/Makefile的语法错误,请按/u-boot-1.1.6/examples/Makefile部分更新;
    D,配置并编译在NANDFLASH中运行模式
     修改配置头文件
     root@yuanxh-desktop:/home/yuanxh/at91_works/u-boot-1.1.5# vi include/configs/at91sam9260ek.h
     把文件中的
     #define CFG_ENV_IS_IN_DATAFLASH         1
  #undef CFG_ENV_IS_IN_NAND
  改成
  #undef  CFG_ENV_IS_IN_DATAFLASH
  #define  CFG_ENV_IS_IN_NAND            1
  重新编译
        root@yuanxh-desktop:/home/yuanxh/at91_works/u-boot-1.1.5# make clean
        root@yuanxh-desktop:/home/yuanxh/at91_works/u-boot-1.1.5# make mrproper
        root@yuanxh-desktop:/home/yuanxh/at91_works/u-boot-1.1.5# make at91sam9260ek_config
        root@yuanxh-desktop:/home/yuanxh/at91_works/u-boot-1.1.5# make
        root@yuanxh-desktop:/home/yuanxh/at91_works/u-boot-1.1.5# mv u-boot.bin u-boot-env-nf.bin
    E,发送目标码
        root@yuanxh-desktop:/home/yuanxh/at91_works/u-boot-1.1.5# sz u-boot-env-df.bin
        root@yuanxh-desktop:/home/yuanxh/at91_works/u-boot-1.1.5# sz u-boot-env-nf.bin

七,为SAM9260编译ARM-LINUX内核

1,传送文件包到LINUX系统并解压
    利用SecureCRT 5.1.3登陆,传送文件到系统
        root@yuanxh-desktop:/home/yuanxh# cd at91_works/
        root@yuanxh-desktop:/home/yuanxh/at91_works# rz
        在SecureCRT弹出的窗口中选择2.6.23-at91.patch.gz和linux-2.6.23.tar.bz2包;
2,解压内核及打上补丁包
        root@yuanxh-desktop:/home/yuanxh/at91_works# tar xjvf linux-2.6.23.tar.bz2
        root@yuanxh-desktop:/home/yuanxh/at91_works# gzip -d 2.6.23-at91.patch.gz
        root@yuanxh-desktop:/home/yuanxh/at91_works# cd linux-2.6.23
        root@yuanxh-desktop:/home/yuanxh/at91_works/linux-2.6.23# patch -p1 < ../2.6.23-at91.patch
3,为内核指定编译器
        root@yuanxh-desktop:/home/yuanxh/at91_works/linux-2.6.23# vi Makefile
        把 EXTRAVERSION = -9gsam9260ek 写上自己版本标识,指定体系结构和编译器
        ARCH           ?= arm
        CROSS_COMPILE  ?= /usr/local/arm/eldk-4.1/usr/bin/arm-linux-
        添加可加载模块安装路径
        INSTALL_MOD_PATH = $(TOPDIR)/modules-$(KERNELRELEASE)
4,编译内核及发布目标码
    A,查看内核支持的开发板
        root@yuanxh-desktop:/home/yuanxh/at91_works/linux-2.6.23# make ARCH=arm CROSS_COMPILE=arm-linux- help
    B,配置为AT91RM9260EK板默认设置
        root@yuanxh-desktop:/home/yuanxh/at91_works/linux-2.6.23# make ARCH=arm CROSS_COMPILE=arm-linux- at91sam9260ek_defconfig
    C,编译生成全部目标码
        root@yuanxh-desktop:/home/yuanxh/at91_works/linux-2.6.23# make ARCH=arm CROSS_COMPILE=arm-linux-
    D,也可分步依次生成zImage,可加载modules和安装可加载模拟到默认目录
        root@yuanxh-desktop:/home/yuanxh/at91_works/linux-2.6.23# make ARCH=arm CROSS_COMPILE=arm-linux- zImage
        root@yuanxh-desktop:/home/yuanxh/at91_works/linux-2.6.23# make ARCH=arm CROSS_COMPILE=arm-linux- modules
        root@yuanxh-desktop:/home/yuanxh/at91_works/linux-2.6.23# make ARCH=arm CROSS_COMPILE=arm-linux- modules_install
    E,发送内核目标码和可加载模块
        root@yuanxh-desktop:/home/yuanxh/at91_works/linux-2.6.23# cp arch/arm/boot/zImage .
        root@yuanxh-desktop:/home/yuanxh/at91_works/linux-2.6.23# mv zImage zImage-2.6.23-9gsam9260ek.bin
        root@yuanxh-desktop:/home/yuanxh/at91_works/linux-2.6.23# sz zImage-2.6.23-9gsam9260ek.bin
        root@yuanxh-desktop:/home/yuanxh/at91_works/linux-2.6.23# tar czvf modules-2.6.23-9gsam9260ek.tar.gz modules-2.6.23-9gsam9260ek/
        root@yuanxh-desktop:/home/yuanxh/at91_works/linux-2.6.23# sz modules-2.6.23-9gsam9260ek.tar.gz
F,个性化配置内核
  root@yuanxh-desktop:/home/yuanxh/at91_works/linux-2.6.23# make ARCH=arm CROSS_COMPILE=arm-linux- menuconfig
  .config中内核启动命令行参数CONFIG_CMDLINE改为:
  mem=64M console=ttyS0,115200 initrd=0x21100000,8388608 root=/dev/ram0 rw init=/linuxrc
G,编译生成U-BOOT可识别目标码uImage
  root@yuanxh-desktop:/home/yuanxh/at91_works/linux-2.6.23# make ARCH=arm CROSS_COMPILE=arm-linux- uImage
  root@yuanxh-desktop:/home/yuanxh/at91_works/linux-2.6.23# cp arch/arm/boot/uImage .
  root@yuanxh-desktop:/home/yuanxh/at91_works/linux-2.6.23# mv uImage uImage-2.6.23-9gsam9260ek.bin
        root@yuanxh-desktop:/home/yuanxh/at91_works/linux-2.6.23# sz uImage-2.6.23-9gsam9260ek.bin
5,清除内核目标码恢复未配置状态
        root@yuanxh-desktop:/home/yuanxh/at91_works/linux-2.6.23# make ARCH=arm CROSS_COMPILE=arm-linux- clean
        root@yuanxh-desktop:/home/yuanxh/at91_works/linux-2.6.23# make ARCH=arm CROSS_COMPILE=arm-linux- distclean
        root@yuanxh-desktop:/home/yuanxh/at91_works/linux-2.6.23# make ARCH=arm CROSS_COMPILE=arm-linux- mrproper


八,编译BUSYBOX建立根文件系统 

1,编译BUSYBOX
A,传送文件包到LINUX系统并解压
     利用SecureCRT 5.1.3登陆,传送文件到系统
  root@yuanxh-desktop:~# cd /home/yuanxh/at91_works/
  root@yuanxh-desktop:/home/yuanxh/at91_works# rz
  在SecureCRT弹出的窗口中选择busybox-1.8.2.tar.bz2包;
B,解压及指定编译器
  root@yuanxh-desktop:/home/yuanxh/at91_works# tar xjvf busybox-1.8.2.tar.bz2
  root@yuanxh-desktop:/home/yuanxh/at91_works# cd busybox-1.8.2
  root@yuanxh-desktop:/home/yuanxh/at91_works/busybox-1.8.2# vi Makefile
        把 EXTRAVERSION = -9gsam9260ek 写上自己版本标识,指定体系结构和编译器
        ARCH           ?= arm
        CROSS_COMPILE  ?= /usr/local/arm/eldk-4.1/usr/bin/arm-linux-
C,编译生成全部目标码
  root@yuanxh-desktop:/home/yuanxh/at91_works/busybox-1.8.2# make help
  root@yuanxh-desktop:/home/yuanxh/at91_works/busybox-1.8.2# make defconfig
  root@yuanxh-desktop:/home/yuanxh/at91_works/busybox-1.8.2# make
  root@yuanxh-desktop:/home/yuanxh/at91_works/busybox-1.8.2# make install
  root@yuanxh-desktop:/home/yuanxh/at91_works/busybox-1.8.2# mv _install/ rootfs
        root@yuanxh-desktop:/home/yuanxh/at91_works/busybox-1.8.2# cp -dpR examples/bootfloppy/etc rootfs/
  root@yuanxh-desktop:/home/yuanxh/at91_works/busybox-1.8.2# tar czvf busybox-9gsam9260ek.tar.gz rootfs/
  root@yuanxh-desktop:/home/yuanxh/at91_works/busybox-1.8.2# sz busybox-9gsam9260ek.tar.gz
D,个性化配置BUSYBOX
  root@yuanxh-desktop:/home/yuanxh/at91_works/busybox-1.8.2# make menuconfig
E,清除内核目标码恢复未配置状态
  root@yuanxh-desktop:/home/yuanxh/at91_works/busybox-1.8.2# make clean
  root@yuanxh-desktop:/home/yuanxh/at91_works/busybox-1.8.2# make distclean
  root@yuanxh-desktop:/home/yuanxh/at91_works/busybox-1.8.2# make mrproper
2,编译RZSZ软件包

A,在http://ftp.uni-koeln.de/util/comm/
  上下载rzsz-3.49.zip
B,上传到LINUX系统
  root@yuanxh-desktop:/home/yuanxh/at91_works# rz
C,解压软件包
  在虚拟机窗口中右击rzsz-3.49.zip,选择“解压到此处”来解压,
D,进入软件包
  root@yuanxh-desktop:/home/yuanxh/at91_works# cd rzsz-3.49
E,指定编译器
  root@yuanxh-desktop:/home/yuanxh/at91_works/rzsz-3.49# vi makefile
  修改如下内容
  CC=/usr/local/arm/eldk-4.1/usr/bin/arm-linux-gcc
F,编译生成目标码
  root@yuanxh-desktop:/home/yuanxh/at91_works/rzsz-3.49# make posix
  root@yuanxh-desktop:/home/yuanxh/at91_works/rzsz-3.49# tar czvf rzsz-9gsam9260ek.tar.gz rz sz
  root@yuanxh-desktop:/home/yuanxh/at91_works/rzsz-3.49# sz rzsz-9gsam9260ek.tar.gz
  注意:此软件有版权保护,软件中REGISTERED如果没有被宏定义,程序在使用中提示使用越权;
3,建立根文件系统
A,建立BUSYBOX基本目录
  root@yuanxh-desktop:/home/yuanxh/at91_works# mkdir rootfs-9g9sam9260ek
  root@yuanxh-desktop:/home/yuanxh/at91_works# cd rootfs-9g9sam9260ek/
  root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek# rz
  传送上节编译生成的busybox-9gsam9260ek.tar.gz目标码包
B,建立树型根目录
  root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek# tar xzvf busybox-9gsam9260ek.tar.gz
  root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek# cd rootfs/
  root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek/rootfs# mkdir -pv app dev home mnt proc sys tmp var opt
  root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek/rootfs# install -dv -m 0750 root
  root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek/rootfs# mkdir -pv var/{lock,log,lib,run,tmp}
  root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek/rootfs# mkdir -pv usr/{lib,share}
  root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek/rootfs# chmod 1777 tmp var/tmp
  root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek/rootfs# mkdir -pv dev/pts 
C,添加动态库文件
  root@yuanxh-desktop:/home/yuanxh# cd /usr/local/arm/eldk-4.1/arm
  root@yuanxh-desktop:/usr/local/arm/eldk-4.1/arm# tar czvf lib-eldk-4.1.tar.gz lib/
  root@yuanxh-desktop:/usr/local/arm/eldk-4.1/arm# mv lib-eldk-4.1.tar.gz /home/yuanxh/at91_works/rootfs-9g9sam9260ek
  root@yuanxh-desktop:/usr/local/arm/eldk-4.1/arm# cd /home/yuanxh/at91_works/rootfs-9g9sam9260ek/rootfs
  root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek/rootfs# tar xzvf ../lib-eldk-4.1.tar.gz
  root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek/rootfs# arm-linux-strip --remove-section=.note --remove-section=.comment lib/*.so
  注意:可以删除部分不常用字的库以减小体积。
  root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek/rootfs/lib# rm -rf *.a *.o security gconv
  root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek/rootfs/lib# rm -rf *.7f *.79 libnss*  libmudflap*
D,添加设备节点
     root@yuanxh-desktop:/home/yuanxh/at91_works# cd rootfs-9g9sam9260ek/rootfs/
     root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek/rootfs# cp -dpR /dev/* dev/
E,添加系统配置
     在etc/inittab中加入以下内容
     #id:3:initdefault:
     #su:S016:once:/sbin/sulogin
     #si::sysinit:/etc/rc.d/init.d/rc sysinit
        #l0:0:wait:/etc/rc.d/init.d/rc 0
       
        3:12345:respawn:/sbin/getty -L ttyS0 115200 vt100
//        ::respawn:/sbin/getty -L ttyS1 115200 vt100
//  ::respawn:/sbin/getty -L ttyS2 115200 vt100
//  ::respawn:/usr/sbin/telnetd
  ::respawn:/usr/sbin/inetd -f
        ::shutdown:/bin/mount / o remount,ro
        #::ctrlaltdel:/sbin/reboot
        #::shutdown:/bin/umount ar
        #ca:12345:ctrlaltdel:/sbin/shutdown -t1 -a -r now

        在etc/fstab中添加入以下内容
        tmpfs   /tmp    tmpfs   defaults    0 0
        sysfs   /sys    sysfs   defaults    0 0
        none    /dev/pts devpts  mode=0622  0 0
        #devpts /dev/pts     devpts gid=4,mode=620  0     0
        #shm    /dev/shm     tmpfs  defaults        0     0

        在etc/profile中添加入以下内容
        #set patch
        PATH=/bin:/sbin:/usr/bin:/usr/sbin
        export PATH
        #alias command
        alias ll='ls -l'
        alias la='ls -a'
        alias du='du -h'
        alias df='df -h'

        在/etc/init.d/rcS中添加入以下内容
        /sbin/ifconfig lo 127.0.0.1
        /sbin/ifconfig eth0 192.168.1.10
        /bin/mount /dev/pts
        dmesg > /var/log/dmesg
        #hostname F /etc/hostname
        hostname 9gsam9260-Linux
        # mount fs
        /bin/mount -o remount,rw /
        # display
        echo 'rootfs version 2.6.23-9gsam9260ek (yuanxihua@y21cn.com) (gcc version 4.0.0 (DENX ELDK 4.1 4.0.0))' > /dev/ttyS0
        cat /root/build_time > /dev/ttyS0
        /app/appinit.sh

        启动/etc/init.d/rcS可执行权限
        root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek/rootfs# chmod a+x /etc/init.d/rcS
       
        命令建立etc/passwd文件
       
  cat > etc/passwd << "EOF"
  root:x:0:0:root:/root:/bin/sh
  EOF
 
  复制部分配置文件
  root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek# cd rootfs/etc/
//  root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek/rootfs/etc# cp /etc/nsswitch.conf .
  root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek/rootfs/etc# cp /etc/group .
  root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek/rootfs/etc# cp /etc/shadow .
  root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek/rootfs/etc# cp /etc/inetd.conf .
  root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek/rootfs/etc# cp /etc/passwd .
 
  修改etc/passwd,使root登陆后执行程序为bin/sh

F,添加可加载模块
     root@yuanxh-desktop:/home/yuanxh/at91_works# cd rootfs-9g9sam9260ek
     root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek# rz
     利用SecureCRT发送modules-2.6.23-9gsam9260ek.tar.gz
     root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek# tar xzvf modules-2.6.23-9gsam9260ek.tar.gz
     root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek# rm -rf rootfs/lib/modules/*
     root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek# mv modules-2.6.23-9gsam9260ek/lib/modules/*  rootfs/lib/modules/
     root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek# rm -rf modules-2.6.23-9gsam9260ek
   
G,添加其它命令和应用程序
     root@yuanxh-desktop:/home/yuanxh/at91_works# cd rootfs-9g9sam9260ek
  root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek# rz
     root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek# cd rootfs/bin/
  root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek/rootfs/bin# tar xzvf ../../rzsz-9gsam9260ek.tar.gz
 
4,打包成RAMDISK根文件系统
A,进入根文件系统目录
  root@yuanxh-desktop:/home/yuanxh/at91_works# cd rootfs-9g9sam9260ek
B,然后执行如下脚本:
  mkdir ramdisk
  dd if=/dev/zero of=ramdisk.img bs=1k count=8192
  mke2fs -F -v -m 0 -N 2000 ramdisk.img
  mount -t ext2 -o loop ramdisk.img  ramdisk
  cp -av rootfs/* ramdisk/
  umount ramdisk
  gzip -9 < ramdisk.img > initrd.bin
  #mv ramdisk.img initrd.bin
  rm -rf ramdisk-2.6.23-9gsam9260ek.bin
  mv initrd.bin  ramdisk-2.6.23-9gsam9260ek.bin
  cp ramdisk-2.6.23-9gsam9260ek.bin /tftpboot/
  rm -rf ramdisk.img
  rm -rf ramdisk
C,发送RAMDISK文件系统目标码
  root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek# sz ramdisk-2.6.23-9gsam9260ek.bin

5,打包成JFFS2根文件系统
A,利用ELDK-4.1中的mkfs.jffs2命令打包
  root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek# mkfs.jffs2 -d rootfs/ -o jffs2-2.6.23-9gsam9260ek.bin
B,发送目标码
  root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek# sz jffs2-2.6.23-9gsam9260ek.bin
C,本机测试JFFS2文件系统
  root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek# rmmod mtdram
  root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek# modprobe mtdram total_size=29568 erase_size=128
  root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek# modprobe mtdblock   
  root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek# modprobe mtdchar
  root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek# cat /proc/mtd
  root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek# dd if=jffs2-2.6.23-9gsam9260ek.bin of=/dev/mtd0
  root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek# mount -t jffs2 /dev/mtdblock0 /mnt
D,修改JFFS2文件系统内容
  添加内容到/mnt,然后执行如下命令:
  root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek# umount /mnt
  root@yuanxh-desktop:/home/yuanxh/at91_works/rootfs-9g9sam9260ek# dd if=/dev/mtd0 of=jffs2-2.6.23-9gsam9260ek.new.bin

九,固化目标码到9GSAM9260EK中 

1,安装ISP工具
    双击Install AT91-ISP v1.10.exe,按NEXT;按I Agree,按NEXT,按install;

9GSAM9260EK V20 linux代码烧录过程

使用dataflash

1.J1接通2-3,J2跳开,J4,J5跳开,连上USB线,识别USB设备后,

2.启动SAM-BA v2.6,用\usb\ARM0和AT91SAM9260-EK配置,进入sam-ba,
选择DataFlash AT45DB/DCB页面,合上J5,

3.在Scripts中选择Enable Dataflash on CS1,点击旁边的Execute,

4.在Scripts中选择Erase All,点击旁边的Execute,

5.在Scripts中选择Send Boot File,在Address框中填入0x0,
点击旁边的Execute,在弹出的打开框中选择
dataflash_at91sam9260ek.bin ,
或者
9gsam9260ek-dfboot.bin ,

6.点击Send File Name框旁边的Browse,在弹出的打开框中选择
u-boot-env-df.bin,
在Internal Address框中填入 0x8000 ,
点击Send File

DATAFLASH空间不足,以下参照NAND部分7,8,9。
{
7.点击Send File Name框旁边的Browse,在弹出的打开框中选择
uImage-2.6.23-9gsam9260ek.bin,
在Internal Address框中填入 0x30000 ,
点击Send File

8.点击Send File Name框旁边的Browse,在弹出的打开框中选择
ramdisk-2.6.23-9gsam9260ek.bin,
在Internal Address框中填入 0x300000 ,
点击Send File

9.连上调试串口,复位9GSAM9260EK,看看效果。
setenv bootcmd cp.b 0xD0030000 0x21500000 0x00200000\;cp.b 0xD0300000 0x21100000 0x00400000\;bootm 0x21500000
回车,再输入
saveenv。
}
10.现在手动烧录完成,复位9GSAM9260EK,进入linux。


使用nandflash


1.J1接通2-3,J2跳开,J4,J5跳开,连上USB线,识别USB设备后,

2.启动SAM-BA v2.6,用\usb\ARM0和AT91SAM9260-EK配置,进入sam-ba,
选择NandFlash页面,合上J4,

3.在Scripts中选择NandFlash Init,点击旁边的Execute,

4.在Scripts中选择NandFlash Erase All,点击旁边的Execute,

5.在Scripts中选择NandFlash Send Boot File,在Address框中填入0x0,
点击旁边的Execute,在弹出的打开框中选择
nandflash_at91sam9260ek.bin,

6.点击Send File Name框旁边的Browse,在弹出的打开框中选择
u-boot-env-nf.bin,
在Address框中填入 0x00020000 ,
点击Send File

7.点击Send File Name框旁边的Browse,在弹出的打开框中选择
uImage-2.6.23-9gsam9260ek.bin,
在Address框中填入 0x00100000 ,
点击Send File

8.点击Send File Name框旁边的Browse,在弹出的打开框中选择
ramdisk-2.6.23-9gsam9260ek.bin,
在Address框中填入 0x00300000 ,
点击Send File

9.连上调试串口,reste 9260-ek,进入u-boot,输入
setenv bootcmd nand read 0x21500000 0x100000 0x200000\;nand read 0x21100000 0x300000 0x400000\;bootm 0x21500000
回车,再输入
saveenv

10.现在手动烧录完成,复位9GSAM9260EK,进入linux。

不用u-boot


1.J1接通2-3,J2跳开,J4,J5跳开,连上USB线,识别USB设备后,

2.启动SAM-BA v2.6,用\usb\ARM0和AT91SAM9260-EK配置,进入sam-ba,
选择NandFlash页面,合上J4,

3.在Scripts中选择NandFlash Init,点击旁边的Execute,

4.在Scripts中选择NandFlash Erase All,点击旁边的Execute,

5.在Scripts中选择NandFlash Send Boot File,在Address框中填入 0x0 ,
点击旁边的Execute,在弹出的打开框中选择
9gsam9260ek-nfboot.bin ,

6.点击Send File Name框旁边的Browse,在弹出的打开框中选择
uImage-2.6.23-9gsam9260ek.bin,
在Address框中填入 0x00100000 ,
点击Send File

7.点击Send File Name框旁边的Browse,在弹出的打开框中选择
ramdisk-2.6.23-9gsam9260ek.bin,
在Address框中填入 0x00300000 ,
点击Send File

8.现在手动烧录完成,连上DEBUG串口,复位9GSAM9260EK,进入linux。


u-boot网络启动

1.在dataflash或者nandflash里烧录上u-boot-env-df.bin或者u-boot-env-nf.bin;

2.连上DEBUG串口,复位9GSAM9260EK,进入 u-boot;

3.u-boot中配置网络环境变量

    setenv serverip 192.168.102.104
    setenv ipaddr 192.168.102.105
    setenv ethaddr 00:11:22:33:44:55
    setenv netmask 255.255.255.0
    setenv hostname 9gsam9260ek
    setenv gatewayip 192.168.102.254
    setenv dnsip 192.168.100.254
    setenv hostname 9gsam9260ek
    saveenv
4.u-boot中配置启动环境变量       
    setenv bootfile /tftpboot/uImage-2.6.23-9gsam9260ek.bin
    setenv rootpath /tftpboot/rootfs
    setenv bootargs mem=64M console=ttyS0,115200 initrd=0x21100000,8388608 root=/dev/ram0 rw init=linuxrc
    saveenv
5.网络下载内核和根文件系统
    tftp 21500000 uImage-2.6.23-9gsam9260ek.bin
    tftp 21100000 ramdisk-2.6.23-9gsam9260ek.bin
    保存自动启动命令
    setenv bootcmd tftp 21500000 uImage-2.6.23-9gsam9260ek.bin\;tftp 21100000 ramdisk-2.6.23-9gsam9260ek.bin\;bootm 0x21500000
    saveenv
6.启动内核
    bootm 0x21500000

十,9GSAM9260EK功能测试 

1,USB转SD卡读卡器
A,插入SD卡读卡器到USB-HOST
B,加载到/MNT
  / # mount /dev/sda1 /mnt
C,查看
  / # ll mnt
 
2,SD卡座
A,补丁
http://marc.info/?l=linux-arm-kernel&m=118036170932720&w=2

3,测试USB-DEVICE
A,外接电源启动进入LINUX建立文件
  / # dd if=/dev/zero of=/tmp/usbramdisk.img bs=1k count=8192
B,执行下面命令安装驱动
  / # insmod /lib/modules/2.6.23-9gsam9260ek/kernel/drivers/usb/gadget/g_file_storage.ko file=/tmp/usbramdisk.img stall=0 removable=1
C,插上USB-DEVICE线到XP
D,在XP会出现插入U盘
E,格式化U盘全可以使用

4,测试网络
    / # ifconfig eth0 192.168.1.10
    / # ping 192.168.1.100
    / # tftp -g 192.168.1.100 -r uImage-2.6.23-9gsam9260ek.bin
5,测试远程登陆
在终端上运行查看IP
/ # ifconfig -a
然后启动telnetd服务器端
    / # /usr/sbin/telnetd
    然后在SecureCRT上建立一个到开发板IP的telnet连接
    测试命令
    ~ # echo abcd > /dev/ttyS0
    在调试串口0上可以看到abcd字符
6,测试其它串口
启用串口1
/ # /sbin/getty -L ttyS1 115200 vt100
串口线接到串口1
在telnet中执行
~ # echo yuanxh > /dev/ttyS1
  在调试串口1上可以看到yuanxh字符
在串口1终端上按回车,可以看到登陆信息
9gsam9260-Linux login:
输入用户名密码登陆后
执行
/sbin/getty -L ttyS2 115200 vt100
    把串口线接到串口2,按回车出现同样登陆信息
    输入用户名密码登陆后就可以登陆。
    在网络telnet登陆中执行
    ~ # echo abcdyuanxh > /dev/ttyS2
    在调试串口2上可以看到abcdyuanxh字符

十,9GSAM9260EK功能测试 

1,USB转SD卡读卡器
A,插入SD卡读卡器到USB-HOST
B,加载到/MNT
  / # mount /dev/sda1 /mnt
C,查看
  / # ll mnt
 
2,SD卡座
A,补丁
http://marc.info/?l=linux-arm-kernel&m=118036170932720&w=2

3,测试USB-DEVICE
A,外接电源启动进入LINUX建立文件
  / # dd if=/dev/zero of=/tmp/usbramdisk.img bs=1k count=8192
B,执行下面命令安装驱动
  / # insmod /lib/modules/2.6.23-9gsam9260ek/kernel/drivers/usb/gadget/g_file_storage.ko file=/tmp/usbramdisk.img stall=0 removable=1
C,插上USB-DEVICE线到XP
D,在XP会出现插入U盘
E,格式化U盘全可以使用

4,测试网络
    / # ifconfig eth0 192.168.1.10
    / # ping 192.168.1.100
    / # tftp -g 192.168.1.100 -r uImage-2.6.23-9gsam9260ek.bin
5,测试远程登陆
在终端上运行查看IP
/ # ifconfig -a
然后启动telnetd服务器端
    / # /usr/sbin/telnetd
    然后在SecureCRT上建立一个到开发板IP的telnet连接
    测试命令
    ~ # echo abcd > /dev/ttyS0
    在调试串口0上可以看到abcd字符
6,测试其它串口
启用串口1
/ # /sbin/getty -L ttyS1 115200 vt100
串口线接到串口1
在telnet中执行
~ # echo yuanxh > /dev/ttyS1
  在调试串口1上可以看到yuanxh字符
在串口1终端上按回车,可以看到登陆信息
9gsam9260-Linux login:
输入用户名密码登陆后
执行
/sbin/getty -L ttyS2 115200 vt100
    把串口线接到串口2,按回车出现同样登陆信息
    输入用户名密码登陆后就可以登陆。
    在网络telnet登陆中执行
    ~ # echo abcdyuanxh > /dev/ttyS2
    在调试串口2上可以看到abcdyuanxh字符


9GSAM9260EK开发板简介 

AT91SAM9260特性
带Java扩展的ARM926EJ-S内核, 2 x 8KB快速缓存, MMU内存管理单元
■ 2x4 KB SRAM, 32 KB Boot ROM
■ 180 MHz时200 MIPS
■ EBI总线可支持SDRAM, NAND Flash (带ECC)和Compact Flash CARD
■ 外设可支持DMA和FIFO,集成复位控制电路,高速中断
■ USB主控制器和USB从设备口, V2.0全速12M
■ Ethernet MAC - 10/100M
■ 图像传感器接口,10BIT接口,支持SAV和EAV
■ 一个 SSC可支持I2S和TDM
■ 两个 SPI, MCI (SD Card和MMC兼容), TWI
■ 六 USART, 支持IrDA, ISO7816 T=0/T=1, RS-485 RS-232 IRDA
■ 一个调试UART
■ 4-通道 10位ADC
■ 带实时时钟的备用电池供电的下电模式
■ 1个主时钟,1个32.768K时钟, 2 PLL和RTC
■ 3.0到3.6V IO电源,1.65到1.95V内核电源, 3.0到3.6V或1.95到3.0V 存储器电源接口
■ JTAG和边际扫描
■ PQFP-208和LFBGA217
开发板特性:
MPU
at91sam9260(PQFP-208,无铅产品)
存储器
■256MB 8位 NandFlash
■64MB  两片16位 SDRAM
■2MB DataFash
电源(Power)
■USB从设备口取电,或者5V外接
网络(Ethernet)
■一个10/100M网口,带网络变压器的RJ-45接口和板上LED指示灯
USB Host端口
■一路USB 2.0 全速12M Host端口
■支持U盘、鼠标、键盘、摄像头、打印机 等设备
USB Device 端口
■一路USB 2.0 全速12M Device端口
串口(USART)
■一个三线串口,一个五线串口,USART支持RS485和ISO7816协议
Dbgu调试口
■一个专用调试串口
实时时钟
■带后备电池的RTC
■一路CAN-Bus接口,支持CAN2.0A/B协议
■一个SD卡接口(四线方式)
■外接SPI和I2C接口
■外接简易EBI接口,可接LCD
■一路AD接口,板上可调电阻
■一路音频录放接口
■一路触摸屏接口
■四个独立GPIO口按键
■一个外置硬件看门狗和电源电压检测
■JTAG调试接口
■USB器件接口固化代码模式
■四个独立GPIO口按键
■一个外置硬件看门狗和电源电压检测
■JTAG调试接口
■USB器件接口固化代码模式

#20 S3C2440/S3C2416/S3C6410/S5PV210 » 常用U-BOOT启动代码命令在GEC2440开发板上的应用 --缥缈九哥 » 2020-05-09 21:11:51

缥缈九哥
回复: 0

常用U-BOOT启动代码命令在GEC2440开发板上的应用

printenv
setenv serverip 192.168.1.108
setenv ipaddr 192.168.1.118
setenv ethaddr 08:08:08:08:12:27
setenv netmask 255.255.255.0
setenv gatewayip 192.168.1.1
setenv bootcmd tftp 30800000 uImage-2.6.26-9g24x0.bin;tftp 31000000 ramdisk-2.6.26-9g24x0.bin;bootm 30800000
setenv bootcmd tftp 30800000 uImage-2.6.26-9g24x0.bin;bootm 30800000
setenv bootargs noinitrd root=/dev/nfs rw nfsroot=192.168.1.108:/nfsboot/rootfs ip=192.168.1.118:192.168.1.108::255.255.255.0 console=ttySAC0,115200 init=/linuxrc mem=64M
setenv bootargs root=/dev/ram0 rw initrd=0x31000000,0x1000000 console=ttySAC0,115200 init=/linuxrc mem=64M

(1) 查看u-boot的环境变量信息
(2) 设置TFTP服务器的IP地址
(3) 设置本机IP地址
(4) 设置本机MAC地址
(5) 设置本机子域掩码
(6) 设置网关IP地址
(7) 设置默认启动命令下载uImage内核,ramdisk根文件系统并启动uImage内核
(8) 设置默认启动命令下载uImage内核,并启动uImage内核
(9) 设置默认内核启动命令行参数,用于NFS根文件系统启动
(10) 设置默认内核启动命令行参数,用于RAMDISK根文件系统启动


nand info
nand device 0
nand bad
setenv autostart yes
nboot 3100000 0 100000

(1) 查看Nand的信息
(2) 查看Nand设备0的信息
(3) 查看Nand的块块
(4) 设置自动启动,让nboot有效调用启动参数和bootm命令
(5) nboot启动nand的 device设备0上100000的uImage,启动地址为SDRAM的3100000

tftp 32000000 uImage
nand erase 0x100000   0x200000
nand write 0x32000000 0x100000 0x200000
nand read  0x31000000 0x100000 0x200000
bootm 31000000

(1) 从网口下载uImage 到SDRAM的0x32000000处
(2) 从1M处开始擦写Nand Flash,擦写2M大小的空间
(3) 将SDRAM中的0x32000000处开始的内容uImage,烧写到Nand Flash的0x100000处开始的2M空间内,掉电能保存。
(4) 将Nand Flash的0x100000处开始的2M空间内容uImage,拷贝到SDRAM中0x31000000处开始的地方
(5) 启动uImage

fli
(1) 查看nor flash的信息

protect off all
erase  80000  1fffff
tftp 32000000 uImage
cp.b 32000000 80000  180000
cp.b 80000 31000000  180000
bootm 31000000

(1) 命令打开nor flash写保护
(2) 从80000 (前512K留给U-BOOT及参数存储空间)处开始擦写nor Flash后面全部,(擦写1M5大小的空间)
(3) 从网口下载uImage 到SDRAM的0x32000000处
(4) 将SDRAM中的0x32000000处开始的内容uImage,烧写到nor Flash的80000处开始的1M5空间内,掉电能保存。
(5) 将nor Flash的80000处开始的1M5空间内容uImage,拷贝到SDRAM中0x31000000处开始的地方
(6) 启动uImage

protect off all
erase  0  5ffff
tftp 32000000 u-boot-fs2410.bin.lcd.bf2
cp.b 32000000 0  5ffff

(1) 命令打开nor flash写保护
(2) 从0处开始擦写nor Flash 384KB 大小的空间
(3) 从网口下载u-boot-fs2410.bin.lcd.bf2 到SDRAM的0x32000000处
(4) 将SDRAM中的0x32000000处开始的内容u-boot-fs2410.bin.lcd.bf2,烧写到nor Flash的0处开始的384KB空间内,掉电能保存。

常用UBUNTU的包管理命令。

dpkg -l | less
dpkg -L abcd
dpkg -S abcdef
dpkg -i   abcd.deb
apt-cache search  abcd
apt-cache show  abcd
apt-get install abcd
apt-get remove  abcd
apt-get--purge remove  abcd
apt-get source abcd

(1) 列出系统中dpkg跟踪到的所有的包
(2) 列出abcd包中包括的文件
(3) 列出abcdef命令属于的软件包
(4) 手动安装abcd.deb软件包
(5) 列出包含abcd字符内容的所有包
(6) 列出abcd包的详细信息
(7) 网络下载安装abcd软件包
(8) 卸载abcd软件包
(9) 完全卸载abcd软件包
(10)网络下载abcd软件包的源码

#21 S3C2440/S3C2416/S3C6410/S5PV210 » 移植directvnc-0.7.5到GEC2440开发板 --缥缈九哥 » 2020-05-09 21:10:47

缥缈九哥
回复: 0

移植directvnc-0.7.5到GEC2440开发板

1,下载解压源码:
root@yuanxh-desktop:/home/yuanxh/s3c2410# wget http://www.adam-lilienthal.de/directvnc/directvnc-0.7.5.tar.gz
root@yuanxh-desktop:/home/yuanxh/s3c2410# tar xzvf directvnc-0.7.5.tar.gz
2,配置编译源码:
root@yuanxh-desktop:/home/yuanxh/s3c2410# cd directvnc-0.7.5
root@yuanxh-desktop:/home/yuanxh/s3c2410/directvnc-0.7.5# ./configure
root@yuanxh-desktop:/home/yuanxh/s3c2410/directvnc-0.7.5# make
(编译有错,不用理会!!!只是生成个用到的config.h)
3,重建源码包目录:
root@yuanxh-desktop:/home/yuanxh/s3c2410/directvnc-0.7.5# cd ..
root@yuanxh-desktop:/home/yuanxh/s3c2410# mkdir directvnc-0.7.5-9g24x0 directvnc-0.7.5-9g24x0/include
root@yuanxh-desktop:/home/yuanxh/s3c2410# cp directvnc-0.7.5/src/*.c  directvnc-0.7.5-9g24x0/
root@yuanxh-desktop:/home/yuanxh/s3c2410# cp directvnc-0.7.5/config.h directvnc-0.7.5-9g24x0/include/
root@yuanxh-desktop:/home/yuanxh/s3c2410# cp directvnc-0.7.5/src/*.h directvnc-0.7.5-9g24x0/include/
4,添加缺少的头文件:
root@yuanxh-desktop:/home/yuanxh/s3c2410# cd directvnc-0.7.5-9g24x0/
root@yuanxh-desktop:/home/yuanxh/s3c2410/directvnc-0.7.5-9g24x0# cp /usr/include/X11/Xmd.h include/
root@yuanxh-desktop:/home/yuanxh/s3c2410/directvnc-0.7.5-9g24x0# cp /usr/include/X11/keysymdef.h include/
root@yuanxh-desktop:/home/yuanxh/s3c2410/directvnc-0.7.5-9g24x0# cp /usr/include/jpeglib.h include/
root@yuanxh-desktop:/home/yuanxh/s3c2410/directvnc-0.7.5-9g24x0# cp /usr/include/jconfig.h include/
root@yuanxh-desktop:/home/yuanxh/s3c2410/directvnc-0.7.5-9g24x0# cp /usr/include/jmorecfg.h include/
5,修改不对的源文件:
A,include/directvnc.h文件:
把31行:  #include <X11/Xmd.h>
修改成: #include <Xmd.h>     // charge by yuanxihua@21cn.com
B,include/keysym.h文件:
把69行: #include <X11/keysymdef.h>
修改成: #include <keysymdef.h> // charge by yuanxihua@21cn.com
C,dfb.c文件:
把33行: DFBCardCapabilities caps;
修改成  DFBGraphicsDeviceDescription caps;  // charge by yuanxihua@21cn.com
(可能是新版本的DFB已经更新了结构体定义)
把45行: DFBCHECK(DirectFBSetOption ("quiet", ""));
修改成  //charge by yuanxihua@21cn.com  DFBCHECK(DirectFBSetOption ("quiet", ""));
(可能是新版本的DFB不支持这种配置)
把70行: DFBCHECK(dfb->GetInputDevice( dfb, DIDID_MOUSE, &mouse ));
修改成  //charge by yuanxihua@21cn.com  DFBCHECK(dfb->GetInputDevice( dfb, DIDID_MOUSE, &mouse ));
(因为我的系统鼠标驱动/dev/input/mouse0 [设备号13,  32]还没有实现)
6,按附录增加Makefile:
root@yuanxh-desktop:/home/yuanxh/s3c2410/directvnc-0.7.5-9g24x0# vi Makefile
7,编译生成目标码:
root@yuanxh-desktop:/home/yuanxh/s3c2410/directvnc-0.7.5-9g24x0# make
(就可以生成可执行文件directvnc)
8,添加库文件到目标板:
root@yuanxh-desktop:/home/yuanxh/s3c2410/directvnc-0.7.5-9g24x0# cd /nfsboot/rootfs/usr/
root@yuanxh-desktop:/nfsboot/rootfs/usr# mkdir directfb
root@yuanxh-desktop:/nfsboot/rootfs/usr# cp -av /usr/directfb/* directfb/
root@yuanxh-desktop:/nfsboot/rootfs/usr# cd ../lib/
root@yuanxh-desktop:/nfsboot/rootfs/lib# cp -av ../usr/directfb/lib/libdirect-1.3.so.0* .
root@yuanxh-desktop:/nfsboot/rootfs/lib# cp -av ../usr/directfb/lib/libdirectfb-1.3.so.0* .
root@yuanxh-desktop:/nfsboot/rootfs/lib# cp -av ../usr/directfb/lib/libfusion-1.3.so.0* .
9,在目标板上运行:
./app/directvnc 192.168.1.2:0 -p 123456
(其中192.168.1.2是运行了VNC服务器的IP地址,:0是启动的服务端口5800后面的偏移号,-p 后是登陆密码
运行过程如果缺什么库请自行交叉编译添加到根文件系统的/lib目录,如libjpeg.so* 和 libz.so* 库)


附录:Makefile 文件:
# Makefile for directvnc-0.7.5-9g24x0, (c) 2008 yuanxihua@21cn.com

CROSS_COMPILE=arm-linux-
PKG_CONFIG =/usr/directfb/lib/pkgconfig
INCLUDE=./include
DIRECTFB=/usr/directfb

CCOPTS = -Wall -O2 -I$(INCLUDE) -I$(DIRECTFB)/include/directfb/ -L$(DIRECTFB)/lib/ \
-ldirectfb  -lfusion -ldirect  -lpthread -ljpeg -lm -lz
ASOPTS =
LDOPTS =

CC = $(CROSS_COMPILE)gcc
AS = $(CROSS_COMPILE)as
LD = $(CROSS_COMPILE)ld

OBJS= args.o cursor.o d3des.o dfb.o getopt.o getopt1.o \
jpeg.o main.o rfb.o sockets.o tight.o vncauth.o

all: $(OBJS)
$(CC) $(CCOPTS) -o directvnc $(OBJS)
cp directvnc /nfsboot/rootfs/app/

.c.o:
$(CC) $(CCOPTS) -c -o $*.o $<

.S.o:
$(AS) $(ASOPTS) -o $*.o $<

clean:
rm -f core *.o *~ *.bak *.tmp

miniclean:
rm -f *.o

#22 S3C2440/S3C2416/S3C6410/S5PV210 » 移植DirectFB-1.3.0到GEC2440开发板--缥缈九哥 » 2020-05-09 21:10:08

缥缈九哥
回复: 0

移植DirectFB-1.3.0到GEC2440开发板

1,下载解压源码:
root@yuanxh-desktop:/home/yuanxh/s3c2410# wget http://www.directfb.org/downloads/Core/DirectFB-1.3.0.tar.gz
root@yuanxh-desktop:/home/yuanxh/s3c2410# tar xzvf DirectFB-1.3.0.tar.gz
root@yuanxh-desktop:/home/yuanxh/s3c2410# mv DirectFB-1.3.0 DirectFB-1.3.0-9g24x0
2,建立编译脚本:
root@yuanxh-desktop:/home/yuanxh/s3c2410# cd DirectFB-1.3.0-9g24x0
root@yuanxh-desktop:/home/yuanxh/s3c2410/DirectFB-1.3.0-9g24x0# ./configure --help
root@yuanxh-desktop:/home/yuanxh/s3c2410/DirectFB-1.3.0-9g24x0# vi mkall
在脚本中填入以下内容:
CC=arm-linux-gcc LD=arm-linux-ld ./configure --prefix=/usr/directfb\
  --host=arm-linux --target=arm-linux\
  --enable-png=no  --enable-jpeg \
  --enable-fbdev --enable-freetype=no --sysconfdir=/etc
make
make install
3,去掉OMAP驱动:
root@yuanxh-desktop:/home/yuanxh/s3c2410/DirectFB-1.3.0-9g24x0# cp gfxdrivers/Makefile.in gfxdrivers/Makefile.in.org
root@yuanxh-desktop:/home/yuanxh/s3c2410/DirectFB-1.3.0-9g24x0# cp gfxdrivers/Makefile.am gfxdrivers/Makefile.am.org
root@yuanxh-desktop:/home/yuanxh/s3c2410/DirectFB-1.3.0-9g24x0# vi gfxdrivers/Makefile.in
把其中299行:$(OMAP_DIR)     \  删除
root@yuanxh-desktop:/home/yuanxh/s3c2410/DirectFB-1.3.0-9g24x0# vi gfxdrivers/Makefile.am
把其中144行:$(OMAP_DIR)     \  删除
(OMAP驱动是TI的OMAP系列CPU专用的,在此应用中缺少头文件,引起编译出错)
4,配置编译安装:
root@yuanxh-desktop:/home/yuanxh/s3c2410/DirectFB-1.3.0-9g24x0# chmod 777 mkall
root@yuanxh-desktop:/home/yuanxh/s3c2410/DirectFB-1.3.0-9g24x0# ./mkall
root@yuanxh-desktop:/home/yuanxh/s3c2410/DirectFB-1.3.0-9g24x0# ll /usr/
5,添加到文件系统:
root@yuanxh-desktop:/usr# cd /nfsboot/rootfs/usr/
root@yuanxh-desktop:/nfsboot/rootfs/usr# mkdir directfb
root@yuanxh-desktop:/nfsboot/rootfs/usr# cp -av /usr/directfb/* directfb/
root@yuanxh-desktop:/nfsboot/rootfs/usr# cd ../lib/
root@yuanxh-desktop:/nfsboot/rootfs/lib# cp -av ../usr/directfb/lib/libdirect-1.3.so.0* .
root@yuanxh-desktop:/nfsboot/rootfs/lib# cp -av ../usr/directfb/lib/libdirectfb-1.3.so.0* .
root@yuanxh-desktop:/nfsboot/rootfs/lib# cp -av ../usr/directfb/lib/libfusion-1.3.so.0* .
6,建立directfb配置脚本:
root@yuanxh-desktop:/nfsboot/rootfs/usr# cd /nfsboot/rootfs
root@yuanxh-desktop:/nfsboot/rootfs# vi etc/directfbrc
在脚本中填入以下内容:
system=fbdev
fbdev=/dev/fb0
mode=320x240
depth=16
pixelformat=RGB16

#23 S3C2440/S3C2416/S3C6410/S5PV210 » 移植busybox-1.13.0到GEC2440开发板 --缥缈九哥 » 2020-05-09 21:09:27

缥缈九哥
回复: 1

移植busybox-1.13.0到GEC2440开发板

1,下载解压源码:
root@yuanxh-desktop:/home/yuanxh/s3c2410# wget http://busybox.net/downloads/busybox-1.13.0.tar.bz2
root@yuanxh-desktop:/home/yuanxh/s3c2410# tar xjvf busybox-1.13.0.tar.bz2
root@yuanxh-desktop:/home/yuanxh/s3c2410# mv busybox-1.13.0 busybox-1.13.0-9g24x0
2,修改Makefile:
root@yuanxh-desktop:/home/yuanxh/s3c2410# cd busybox-1.13.0-9g24x0/
root@yuanxh-desktop:/home/yuanxh/s3c2410/busybox-1.13.0-9g24x0# cp Makefile Makefile.org
root@yuanxh-desktop:/home/yuanxh/s3c2410/busybox-1.13.0-9g24x0# vi Makefile
把第4行: EXTRAVERSION =
修改成: EXTRAVERSION =-9g24x0
把第164行: CROSS_COMPILE ?=
修改成: CROSS_COMPILE ?=arm-linux-
3,默认配置:
root@yuanxh-desktop:/home/yuanxh/s3c2410/busybox-1.13.0-9g24x0# make help
root@yuanxh-desktop:/home/yuanxh/s3c2410/busybox-1.13.0-9g24x0# make defconfig
root@yuanxh-desktop:/home/yuanxh/s3c2410/busybox-1.13.0-9g24x0# make
3,修改配置:
root@yuanxh-desktop:/home/yuanxh/s3c2410/busybox-1.13.0-9g24x0# make menuconfig
root@yuanxh-desktop:/home/yuanxh/s3c2410/busybox-1.13.0-9g24x0# make
root@yuanxh-desktop:/home/yuanxh/s3c2410/busybox-1.13.0-9g24x0# make install
root@yuanxh-desktop:/home/yuanxh/s3c2410/busybox-1.13.0-9g24x0# tar czvf busybox-1.13.0-9g24x0-bin.tar.gz _install/
4,安装到文件系统:
root@yuanxh-desktop:/home/yuanxh/s3c2410/busybox-1.13.0-9g24x0# rm -rf /nfsboot/rootfs/bin/ /nfsboot/rootfs/sbin/ /nfsboot/rootfs/usr/ /nfsboot/rootfs/linuxrc
root@yuanxh-desktop:/home/yuanxh/s3c2410/busybox-1.13.0-9g24x0# mv _install/*   /nfsboot/rootfs/

#24 S3C2440/S3C2416/S3C6410/S5PV210 » 添加touchscreen驱动到基于linux-2.6.26的GEC2440开发板 --缥缈九哥 » 2020-05-09 21:08:36

缥缈九哥
回复: 0

添加touchscreen驱动到基于linux-2.6.26的GEC2440开发板

1,修改drivers/input/touchscreen/Makefile文件
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26-9g24x0# vi drivers/input/touchscreen/Makefile
在第24行添加:

obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o

2,修改drivers/input/touchscreen/Kconfig文件
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26-9g24x0# vi drivers/input/touchscreen/Kconfig
在第188行添加:

 config TOUCHSCREEN_S3C2410
  tristate "Samsung S3C2410 touchscreen input driver"
  depends on ARCH_SMDK2410 && INPUT && INPUT_TOUCHSCREEN
  select SERIO
  help
    Say Y here if you have the s3c2410 touchscreen.
    If unsure, say N.
    To compile this driver as a module, choose M here: the
    module will be called s3c2410_ts.
 
 config TOUCHSCREEN_S3C2410_DEBUG
  boolean "Samsung S3C2410 touchscreen debug messages"
  depends on TOUCHSCREEN_S3C2410
  help
    Select this if you want debug messages
 

3,编译配置内核
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26-9g24x0# make menuconfig
进入配置菜单添加驱动到内核:

 Device Drivers  --->
 Input device support  --->
 [*]   Touchscreens  --->
 <*>   Samsung S3C2410 touchscreen input driver
 [*]     Samsung S3C2410 touchscreen debug messages

4,修改arch/arm/mach-s3c2440/mach-smdk2440.c文件
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26-9g24x0# vi arch/arm/mach-s3c2440/mach-smdk2440.c
在166行添加:
  static struct s3c2410_ts_mach_info gec2440_ts_cfg __initdata = {
  .delay = 10000,
  .presc = 49,
  .oversampling_shift = 2,
  };

在static struct platform_device *smdk2440_devices[] __initdata = {结构中添加:
  &s3c_device_ts,
 
在static void __init smdk2440_map_io(void)函数中添加:
  s3c24xx_init_touchscreen(&gec2440_ts_cfg);

5,修改include/asm-arm/plat-s3c24xx/devs.h文件
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26-9g24x0# vi include/asm-arm/plat-s3c24xx/devs.h
在第18行添加:
// add by yuanxihua@21cn.com
struct s3c2410_ts_mach_info {
        int             delay;
        int             presc;
        int             oversampling_shift;
};
void __init s3c24xx_init_touchscreen(struct s3c2410_ts_mach_info *hard_s3c2410_ts_info);
extern struct platform_device s3c_device_ts;
// add by yuanxihua@21cn.com

6,修改arch/arm/plat-s3c24xx/devs.c文件
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26-9g24x0# vi  arch/arm/plat-s3c24xx/devs.c
在第598行添加:
// add by yuanxihua@21cn.com

//  Touchscreen

static struct s3c2410_ts_mach_info s3c2410_ts_info;

void __init s3c24xx_init_touchscreen(struct s3c2410_ts_mach_info *hard_s3c2410_ts_info)
{
  memcpy(&s3c2410_ts_info,hard_s3c2410_ts_info,sizeof(struct s3c2410_ts_mach_info));
}

EXPORT_SYMBOL(s3c24xx_init_touchscreen);

struct platform_device s3c_device_ts = {
  .name = "s3c2410-ts",
  .id = -1,
  .num_resources   = ARRAY_SIZE(s3c_adc_resource),
  .resource   = s3c_adc_resource,
  .dev = {
   .platform_data = &s3c2410_ts_info,
  }
};
EXPORT_SYMBOL(s3c_device_ts);
// add by yuanxihua@21cn.com

7,添加drivers/input/touchscreen/s3c2410_ts.c文件
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26-9g24x0# vi drivers/input/touchscreen/s3c2410_ts.c
添加的源码见附件。

8,编译内核生成驱动
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26-9g24x0# make

9,在内核启动可以看到input: s3c2410 Touchscreen as /class/input/input0
注册信息为:
# cat /proc/bus/input/devices
I: Bus=0019 Vendor=0001 Product=0002 Version=0100
N: Name="s3c2410 Touchscreen"
P: Phys=s3c2410ts/input0
S: Sysfs=/class/input/input0
U: Uniq=
H: Handlers=mouse0 event0
B: EV=b
B: KEY=400 0 0 0 0 0 0 0 0 0 0
B: ABS=1000003

设备结点为:
# ll  /dev/input/
crw-rw----    1 root     root      13,  64 Dec 10  2008 event0
crw-rw----    1 root     root      13,  32 Dec  7  2008 mouse0

附件:

/* drivers/input/touchscreen/s3c2410_ts.c
 *
 *  Touchscreen driver for GEC2440 with Samsung S3C2440A
 *
 *  modify from corgi_ts.c
 *
 *  Copyright (c) 2004-2005 Richard Purdie
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License version 2 as
 *  published by the Free Software Foundation.
 *
 */


#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/init.h>
#include <linux/serio.h>
#include <linux/irq.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/plat-s3c/regs-adc.h>
#include <asm/arch/regs-gpio.h>
#include <asm/arch/regs-clock.h>
#include <asm/plat-s3c24xx/devs.h>
#include <asm/plat-s3c24xx/clock.h>


#define WAIT4INT(x) (((x)<<8) | \
  S3C2410_ADCTSC_YM_SEN | S3C2410_ADCTSC_YP_SEN | S3C2410_ADCTSC_XP_SEN | \
  S3C2410_ADCTSC_XY_PST(3))

#define AUTOPST (S3C2410_ADCTSC_YM_SEN | S3C2410_ADCTSC_YP_SEN | S3C2410_ADCTSC_XP_SEN | \
  S3C2410_ADCTSC_AUTO_PST | S3C2410_ADCTSC_XY_PST(0))

#define DEBUG_LVL    KERN_DEBUG

#define X_AXIS_MAX  0x3ff
#define X_AXIS_MIN  0
#define Y_AXIS_MAX  0x3ff
#define Y_AXIS_MIN  0
#define PRESSURE_MIN 0
#define PRESSURE_MAX 1

/*
 * Definitions & global arrays.
 */

/*
 * Per-touchscreen data.
 */
struct ts_event {
 short pressure;
 short xp;
 short yp;
};
struct s3c2410_ts {
 struct input_dev *input;
 struct resource *res;
 struct timer_list timer;
 struct ts_event tc;
 int pendown;
 int count;
 int shift;
 struct resource *irq_gpio[2];
 struct s3c2410_ts_mach_info *machinfo;
};

static void __iomem *base_addr;

static inline void s3c2410_ts_connect(void)
{
 s3c2410_gpio_cfgpin(S3C2410_GPG12, S3C2410_GPG12_XMON);
 s3c2410_gpio_cfgpin(S3C2410_GPG13, S3C2410_GPG13_nXPON);
 s3c2410_gpio_cfgpin(S3C2410_GPG14, S3C2410_GPG14_YMON);
 s3c2410_gpio_cfgpin(S3C2410_GPG15, S3C2410_GPG15_nYPON);
}

static void touch_timer_fire(struct s3c2410_ts *s3c2410_ts,unsigned long data)
{
   unsigned long data0;
   unsigned long data1;
 struct input_dev *dev = s3c2410_ts->input;

 /* Disable Interrupt */
 set_irq_type(s3c2410_ts->irq_gpio[0]->start, IRQT_NOEDGE);
 set_irq_type(s3c2410_ts->irq_gpio[1]->start, IRQT_NOEDGE);
   
   data0 = readl(base_addr+S3C2410_ADCDAT0);
   data1 = readl(base_addr+S3C2410_ADCDAT1);

  s3c2410_ts->pendown = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) && (!(data1 & S3C2410_ADCDAT0_UPDOWN));

  if (s3c2410_ts->pendown) {
   if (s3c2410_ts->count != 0) {
    s3c2410_ts->tc.xp >>= s3c2410_ts->shift;
    s3c2410_ts->tc.yp >>= s3c2410_ts->shift;

#ifdef CONFIG_TOUCHSCREEN_S3C2410_DEBUG

    {
     struct timeval tv;
     do_gettimeofday(&tv);
     printk(KERN_INFO "T: %06d, X: %03x, Y: %03x\n", (int)tv.tv_usec, s3c2410_ts->tc.xp, s3c2410_ts->tc.yp);
    }
#endif
    input_report_abs(dev, ABS_X, s3c2410_ts->tc.xp);
    input_report_abs(dev, ABS_Y, s3c2410_ts->tc.yp);
   input_report_abs(dev, ABS_PRESSURE, s3c2410_ts->tc.pressure);
   input_report_key(dev, BTN_TOUCH, s3c2410_ts->pendown);
   input_sync(dev);
   }

   s3c2410_ts->tc.xp = 0;
   s3c2410_ts->tc.yp = 0;
   s3c2410_ts->count = 0;
  s3c2410_ts->tc.pressure = 0;

   writel(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST, base_addr+S3C2410_ADCTSC);
   writel(readl(base_addr+S3C2410_ADCCON) | S3C2410_ADCCON_ENABLE_START, base_addr+S3C2410_ADCCON);
  } else {
   s3c2410_ts->count = 0;

   input_report_key(dev, BTN_TOUCH, 0);
   input_report_abs(dev, ABS_PRESSURE, 0);
   input_sync(dev);

   writel(WAIT4INT(0), base_addr+S3C2410_ADCTSC);
  }
  
 /* Enable Falling Edge */
 set_irq_type(s3c2410_ts->irq_gpio[0]->start, IRQT_BOTHEDGE);
 set_irq_type(s3c2410_ts->irq_gpio[1]->start, IRQT_BOTHEDGE);
}
static void s3c2410_ts_timer(unsigned long data)
{
 struct s3c2410_ts *s3c2410ts_data = (struct s3c2410_ts *) data;

 touch_timer_fire(s3c2410ts_data, 1);
}

static irqreturn_t stylus_updown(int irq, void *dev_id, struct pt_regs *regs)
{
 unsigned long data0;
 unsigned long data1;
 struct s3c2410_ts *s3c2410_ts = dev_id;

#ifdef CONFIG_TOUCHSCREEN_S3C2410_DEBUG  
 printk(KERN_ERR "%s() No.%d line:\n\r",__FUNCTION__,__LINE__);
#endif

 data0 = readl(base_addr+S3C2410_ADCDAT0);
 data1 = readl(base_addr+S3C2410_ADCDAT1);

 s3c2410_ts->pendown = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) && (!(data1 & S3C2410_ADCDAT1_UPDOWN));

 /* TODO we should never get an interrupt with updown set while
  * the timer is running, but maybe we ought to verify that the
  * timer isn't running anyways. */

 if (s3c2410_ts->pendown)
  touch_timer_fire(s3c2410_ts, 0);

 return IRQ_HANDLED;
}


static irqreturn_t stylus_action(int irq, void *dev_id, struct pt_regs *regs)
{
 unsigned long data0;
 unsigned long data1;
 struct s3c2410_ts *s3c2410_ts = dev_id;

#ifdef CONFIG_TOUCHSCREEN_S3C2410_DEBUG 
 printk(KERN_ERR "%s() No.%d line:\n\r",__FUNCTION__,__LINE__);
#endif

 data0 = readl(base_addr+S3C2410_ADCDAT0);
 data1 = readl(base_addr+S3C2410_ADCDAT1);

 s3c2410_ts->tc.xp += data0 & S3C2410_ADCDAT0_XPDATA_MASK;
 s3c2410_ts->tc.yp += data1 & S3C2410_ADCDAT1_YPDATA_MASK;
 s3c2410_ts->count++;
 s3c2410_ts->tc.pressure = 1;

 if (s3c2410_ts->count < (1<<s3c2410_ts->shift)) {
  writel(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST, base_addr+S3C2410_ADCTSC);
  writel(readl(base_addr+S3C2410_ADCCON) | S3C2410_ADCCON_ENABLE_START, base_addr+S3C2410_ADCCON);
 } else {
  mod_timer(&s3c2410_ts->timer, jiffies + HZ / 100);
  writel(WAIT4INT(1), base_addr+S3C2410_ADCTSC);
 }

 return IRQ_HANDLED;
}

static struct clk *adc_clock;
/*
 * The functions for inserting/removing us as a module.
 */

#define s3c2410ts_suspend  NULL
#define s3c2410ts_resume  NULL
static int __init s3c2410ts_probe(struct platform_device *pdev)
{
 struct s3c2410_ts *s3c2410_ts;
 struct input_dev *input_dev;
 int size;
 int err = -ENOMEM;

 s3c2410_ts = kzalloc(sizeof(struct s3c2410_ts), GFP_KERNEL);
 input_dev = input_allocate_device();
 if (!s3c2410_ts || !input_dev)
  goto fail1;

 platform_set_drvdata(pdev, s3c2410_ts);

 s3c2410_ts->machinfo = pdev->dev.platform_data;
 s3c2410_ts->irq_gpio[0] = platform_get_resource(pdev, IORESOURCE_IRQ,0);
 s3c2410_ts->irq_gpio[1] = platform_get_resource(pdev, IORESOURCE_IRQ,1);
 
#ifdef CONFIG_TOUCHSCREEN_S3C2410_DEBUG 
 printk(KERN_ERR "s3c2410_ts->irq_gpio[0] = %d,IRQ_TC  = %d\n",s3c2410_ts->irq_gpio[0]->start,IRQ_TC);
 printk(KERN_ERR "s3c2410_ts->irq_gpio[1] = %d,IRQ_ADC = %d\n",s3c2410_ts->irq_gpio[1]->start,IRQ_ADC);
#endif
 
 if ((s3c2410_ts->irq_gpio[0]->start < 0)|(s3c2410_ts->irq_gpio[1]->start < 0)) {
  err = -ENODEV;
  printk(KERN_ERR "Hm... too bad : no irq for ts\n");
  goto fail1;
 }
  
    if (!s3c2410_ts->machinfo)
    {
        printk(KERN_ERR "Hm... too bad : no platform data for ts\n");
  return -EINVAL;
    }
 s3c2410_ts->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 if (s3c2410_ts->res == NULL) {
  printk(KERN_ERR "no memory resource specified\n");
  return -ENOENT;
 }

 adc_clock = clk_get(NULL, "adc");
 if (!adc_clock) {
  printk(KERN_ERR "failed to get adc clock source\n");
  return -ENOENT;
 }
 clk_enable(adc_clock);
  
 size = (s3c2410_ts->res->end-s3c2410_ts->res->start)+1;
 base_addr=ioremap(s3c2410_ts->res->start, size);

#ifdef CONFIG_TOUCHSCREEN_S3C2410_DEBUG 
 printk(KERN_ERR "ioremap %08x to base_addr=%08x , size=%08x\n",s3c2410_ts->res->start,(unsigned int)base_addr,size);
#endif 
 
 if (base_addr == NULL) {
        printk(KERN_ERR "Failed to remap register block\n");
        return -ENOMEM;
    }

 /* Configure GPIOs */
    s3c2410_ts_connect();
   
#ifdef CONFIG_TOUCHSCREEN_S3C2410_DEBUG
    printk(KERN_ERR "s3c2410_ts->machinfo delay = %d,presc = %d,oversampling_shift = %d\n",
    s3c2410_ts->machinfo->delay,
    s3c2410_ts->machinfo->presc,
    s3c2410_ts->machinfo->oversampling_shift);
#endif

 if ((s3c2410_ts->machinfo->presc&0xff) > 0)
        writel(S3C2410_ADCCON_PRSCEN | S3C2410_ADCCON_PRSCVL(s3c2410_ts->machinfo->presc&0xFF),\
        base_addr+S3C2410_ADCCON);
 else
        writel(0,base_addr+S3C2410_ADCCON);


    /* Initialise the adcdly registers */
    if ((s3c2410_ts->machinfo->delay&0xffff) > 0)
        writel(s3c2410_ts->machinfo->delay & 0xffff,  base_addr+S3C2410_ADCDLY);

 writel(WAIT4INT(0), base_addr+S3C2410_ADCTSC);
 __raw_writel(__raw_readl(S3C2410_GPGCON)|(0xff<<24), S3C2410_GPGCON);
 
 s3c2410_ts->input = input_dev;

 init_timer(&s3c2410_ts->timer);
 s3c2410_ts->timer.data = (unsigned long) s3c2410_ts;
 s3c2410_ts->timer.function = s3c2410_ts_timer;
 
// input_dev->private = s3c2410_ts;
 input_dev->name = "s3c2410 Touchscreen";
 input_dev->phys = "s3c2410ts/input0";
 input_dev->id.bustype = BUS_HOST;
 input_dev->id.vendor = 0x0001;
 input_dev->id.product = 0x0002;
 input_dev->id.version = 0x0100;
// input_dev->dev.parent = &pdev->dev;
 
 s3c2410_ts->shift = s3c2410_ts->machinfo->oversampling_shift;
 
 input_dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
 input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
 input_set_abs_params(input_dev, ABS_X, X_AXIS_MIN, X_AXIS_MAX, 0, 0);
 input_set_abs_params(input_dev, ABS_Y, Y_AXIS_MIN, Y_AXIS_MAX, 0, 0);
 input_set_abs_params(input_dev, ABS_PRESSURE, PRESSURE_MIN, PRESSURE_MAX, 0, 0);

 /* Get irqs */
    if (request_irq(s3c2410_ts->irq_gpio[1]->start, stylus_action,  IRQF_DISABLED, pdev->name, s3c2410_ts)) {
        printk(KERN_ERR "s3c2410_ts.c: Could not allocate ts IRQ_ADC !\n");
  iounmap(base_addr);
  err = -EBUSY;
  goto fail1;
 }
    if (request_irq(s3c2410_ts->irq_gpio[0]->start, stylus_updown,  IRQF_DISABLED, pdev->name, s3c2410_ts)) {
        printk(KERN_ERR "s3c2410_ts.c: Could not allocate ts IRQ_TC !\n");
  iounmap(base_addr);
  err = -EBUSY;
  goto fail1;
 }
    /* All went ok, so register to the input system */
 err = input_register_device(s3c2410_ts->input);
 if (err)
  goto fail2;
 /* Enable Falling Edge */
 set_irq_type(s3c2410_ts->irq_gpio[0]->start, IRQT_BOTHEDGE);
 set_irq_type(s3c2410_ts->irq_gpio[1]->start, IRQT_BOTHEDGE);
 return 0;

 fail2: free_irq(s3c2410_ts->irq_gpio, s3c2410_ts);
 fail1: input_free_device(input_dev);
 kfree(s3c2410_ts);
 return err;
}

static int s3c2410ts_remove(struct platform_device *pdev)
{
 struct s3c2410_ts *s3c2410_ts = platform_get_drvdata(pdev);
 
 disable_irq(s3c2410_ts->irq_gpio[0]->start);
 disable_irq(s3c2410_ts->irq_gpio[1]->start);
 free_irq(s3c2410_ts->irq_gpio[0]->start,s3c2410_ts);
 free_irq(s3c2410_ts->irq_gpio[1]->start,s3c2410_ts);
 del_timer_sync(&s3c2410_ts->timer);

 if (adc_clock) {
  clk_disable(adc_clock);
  clk_put(adc_clock);
  adc_clock = NULL;
 }
 input_unregister_device(s3c2410_ts->input);
 iounmap(base_addr);
 kfree(s3c2410_ts);
 return 0;
}

static struct platform_driver s3c2410ts_driver = {
 .probe  = s3c2410ts_probe,
 .remove  = s3c2410ts_remove,
 .suspend = s3c2410ts_suspend,
 .resume  = s3c2410ts_resume,
 .driver  = {
  .name = "s3c2410-ts",
  .owner = THIS_MODULE,
 },
};


static int __devinit s3c2410ts_init(void)
{
 return platform_driver_register(&s3c2410ts_driver);
}

static void __exit s3c2410ts_exit(void)
{
 platform_driver_unregister(&s3c2410ts_driver);
}

module_init(s3c2410ts_init);
module_exit(s3c2410ts_exit);

MODULE_AUTHOR("9g2440 <yuanxihua@21cn.com>");
MODULE_DESCRIPTION("s3c2440 TouchScreen Driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:s3c2410-ts");

#25 S3C2440/S3C2416/S3C6410/S5PV210 » 添加CS8900A的NET驱动到基于linux-2.6.26的GEC2440开发板 --缥缈九哥 » 2020-05-09 21:04:22

缥缈九哥
回复: 0

添加CS8900A的NET驱动到基于linux-2.6.26的GEC2440开发板

1,修改drivers/net/arm/Makefile文件
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26-9g24x0# vi drivers/net/arm/Makefile
在第12行添加:

obj-$(CONFIG_ARM_CS8900) += cs8900.o

2,修改drivers/net/arm/Kconfig文件
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26-9g24x0# vi drivers/net/arm/Kconfig
在第5行添加:

config ARM_CS8900
  tristate "CS8900 support"
  depends on NET_ETHERNET && ARM && ARCH_SMDK2410
  help
   support for cs8900 chipset based Ethernet cards , if you  have a network card of this type.
 
3,编译配置内核
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26-9g24x0# make menuconfig
进入配置菜单添加驱动到内核:

 Device Drivers  --->
 [*] Network device support  --->
 [*]   Ethernet (10 or 100Mbit)  ---> 
 <*>   CS8900 support  

4,修改arch/arm/mach-s3c2440/mach-smdk2440.c文件
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26-9g24x0# vi arch/arm/mach-s3c2440/mach-smdk2440.c
在static struct map_desc smdk2440_iodesc[] __initdata 最后添加:
, {
  .virtual = (u32)0xE0000000,
  .pfn  = __phys_to_pfn(S3C2410_CS3 + (1<<24)),
  .length  = SZ_1M,
  .type  = MT_DEVICE,
}//change by yuanxihua@21cn.com

5,修改include/asm-arm/plat-s3c24xx/common-smdk.h文件
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26-9g24x0# vi include/asm-arm/plat-s3c24xx/common-smdk.h
在14行添加:
//change by yuanxihua@21cn.com
#define pSMDK2410_ETH_IO                 __phys_to_pfn(0x19000000)
#define vSMDK2410_ETH_IO                0xE0000000
#define SMDK2410_ETH_IRQ                 IRQ_EINT9

6,添加drivers/net/arm/cs8900.h文件
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26-9g24x0# vi drivers/net/arm/cs8900.h
添加的源码见附件。
7,添加drivers/net/arm/cs8900.c文件
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26-9g24x0# vi drivers/net/arm/cs8900.c
添加的源码见附件。
8, 编译内核生成驱动
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26-9g24x0# make

附件:
//drivers/net/arm/cs8900.h

#ifndef CS8900_H
#define CS8900_H

/*
 * linux/drivers/net/cs8900.h
 *
 * Author: Abraham van der Merwe <abraham at 2d3d.co.za>
 *
 * A Cirrus Logic CS8900A driver for Linux
 * based on the cs89x0 driver written by Russell Nelson,
 * Donald Becker, and others.
 *
 * This source code is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * version 2 as published by the Free Software Foundation.
 */

/*
 * Ports
 */

#define PP_Address  0x0a /* PacketPage Pointer Port (Section 4.10.10) */
#define PP_Data   0x0c /* PacketPage Data Port (Section 4.10.10) */

/*
 * Registers
 */

#define PP_ProductID  0x0000 /* Section 4.3.1   Product Identification Code */
#define PP_MemBase   0x002c /* Section 4.9.2   Memory Base Address Register */
#define PP_IntNum   0x0022 /* Section 3.2.3   Interrupt Number */
#define PP_EEPROMCommand 0x0040 /* Section 4.3.11  EEPROM Command */
#define PP_EEPROMData  0x0042 /* Section 4.3.12  EEPROM Data */
#define PP_RxCFG   0x0102 /* Section 4.4.6   Receiver Configuration */
#define PP_RxCTL   0x0104 /* Section 4.4.8   Receiver Control */
#define PP_TxCFG   0x0106 /* Section 4.4.9   Transmit Configuration */
#define PP_BufCFG   0x010a /* Section 4.4.12  Buffer Configuration */
#define PP_LineCTL   0x0112 /* Section 4.4.16  Line Control */
#define PP_SelfCTL   0x0114 /* Section 4.4.18  Self Control */
#define PP_BusCTL   0x0116 /* Section 4.4.20  Bus Control */
#define PP_TestCTL   0x0118 /* Section 4.4.22  Test Control */
#define PP_ISQ    0x0120 /* Section 4.4.5   Interrupt Status Queue */
#define PP_TxEvent   0x0128 /* Section 4.4.10  Transmitter Event */
#define PP_BufEvent   0x012c /* Section 4.4.13  Buffer Event */
#define PP_RxMISS   0x0130 /* Section 4.4.14  Receiver Miss Counter */
#define PP_TxCOL   0x0132 /* Section 4.4.15  Transmit Collision Counter */
#define PP_SelfST   0x0136 /* Section 4.4.19  Self Status */
#define PP_BusST   0x0138 /* Section 4.4.21  Bus Status */
#define PP_TxCMD   0x0144 /* Section 4.4.11  Transmit Command */
#define PP_TxLength   0x0146 /* Section 4.5.2   Transmit Length */
#define PP_IA    0x0158 /* Section 4.6.2   Individual Address (IEEE Address) */
#define PP_RxStatus   0x0400 /* Section 4.7.1   Receive Status */
#define PP_RxLength   0x0402 /* Section 4.7.1   Receive Length (in bytes) */
#define PP_RxFrame   0x0404 /* Section 4.7.2   Receive Frame Location */
#define PP_TxFrame   0x0a00 /* Section 4.7.2   Transmit Frame Location */

/*
 * Values
 */

/* PP_IntNum */
#define INTRQ0   0x0000
#define INTRQ1   0x0001
#define INTRQ2   0x0002
#define INTRQ3   0x0003

/* PP_ProductID */
#define EISA_REG_CODE 0x630e
#define REVISION(x)  (((x) & 0x1f00) >> 8)
#define VERSION(x)  ((x) & ~0x1f00)

#define CS8900A   0x0000
#define REV_B   7
#define REV_C   8
#define REV_D   9

/* PP_RxCFG */
#define Skip_1   0x0040
#define StreamE   0x0080
#define RxOKiE   0x0100
#define RxDMAonly  0x0200
#define AutoRxDMAE  0x0400
#define BufferCRC  0x0800
#define CRCerroriE  0x1000
#define RuntiE   0x2000
#define ExtradataiE  0x4000

/* PP_RxCTL */
#define IAHashA   0x0040
#define PromiscuousA 0x0080
#define RxOKA   0x0100
#define MulticastA  0x0200
#define IndividualA  0x0400
#define BroadcastA  0x0800
#define CRCerrorA  0x1000
#define RuntA   0x2000
#define ExtradataA  0x4000

/* PP_TxCFG */
#define Loss_of_CRSiE 0x0040
#define SQErroriE  0x0080
#define TxOKiE   0x0100
#define Out_of_windowiE 0x0200
#define JabberiE  0x0400
#define AnycolliE  0x0800
#define T16colliE  0x8000

/* PP_BufCFG */
#define SWint_X   0x0040
#define RxDMAiE   0x0080
#define Rdy4TxiE  0x0100
#define TxUnderruniE 0x0200
#define RxMissiE  0x0400
#define Rx128iE   0x0800
#define TxColOvfiE  0x1000
#define MissOvfloiE  0x2000
#define RxDestiE  0x8000

/* PP_LineCTL */
#define SerRxON   0x0040
#define SerTxON   0x0080
#define AUIonly   0x0100
#define AutoAUI_10BT 0x0200
#define ModBackoffE  0x0800
#define PolarityDis  0x1000
#define L2_partDefDis 0x2000
#define LoRxSquelch  0x4000

/* PP_SelfCTL */
#define RESET   0x0040
#define SWSuspend  0x0100
#define HWSleepE  0x0200
#define HWStandbyE  0x0400
#define HC0E   0x1000
#define HC1E   0x2000
#define HCB0   0x4000
#define HCB1   0x8000

/* PP_BusCTL */
#define ResetRxDMA  0x0040
#define DMAextend  0x0100
#define UseSA   0x0200
#define MemoryE   0x0400
#define DMABurst  0x0800
#define IOCHRDYE  0x1000
#define RxDMAsize  0x2000
#define EnableRQ  0x8000

/* PP_TestCTL */
#define DisableLT  0x0080
#define ENDECloop  0x0200
#define AUIloop   0x0400
#define DisableBackoff 0x0800
#define FDX    0x4000

/* PP_ISQ */
#define RegNum(x) ((x) & 0x3f)
#define RegContent(x) ((x) & ~0x3d)

#define RxEvent   0x0004
#define TxEvent   0x0008
#define BufEvent  0x000c
#define RxMISS   0x0010
#define TxCOL   0x0012

/* PP_RxStatus */
#define IAHash   0x0040
#define Dribblebits  0x0080
#define RxOK   0x0100
#define Hashed   0x0200
#define IndividualAdr 0x0400
#define Broadcast  0x0800
#define CRCerror  0x1000
#define Runt   0x2000
#define Extradata  0x4000

#define HashTableIndex(x) ((x) >> 0xa)

/* PP_TxCMD */
#define After5   0
#define After381  1
#define After1021  2
#define AfterAll  3
#define TxStart(x) ((x) << 6)

#define Force   0x0100
#define Onecoll   0x0200
#define InhibitCRC  0x1000
#define TxPadDis  0x2000

/* PP_BusST */
#define TxBidErr  0x0080
#define Rdy4TxNOW  0x0100

/* PP_TxEvent */
#define Loss_of_CRS  0x0040
#define SQEerror  0x0080
#define TxOK   0x0100
#define Out_of_window 0x0200
#define Jabber   0x0400
#define T16coll   0x8000

#define TX_collisions(x) (((x) >> 0xb) & ~0x8000)

/* PP_BufEvent */
#define SWint   0x0040
#define RxDMAFrame  0x0080
#define Rdy4Tx   0x0100
#define TxUnderrun  0x0200
#define RxMiss   0x0400
#define Rx128   0x0800
#define RxDest   0x8000

/* PP_RxMISS */
#define MissCount(x) ((x) >> 6)

/* PP_TxCOL */
#define ColCount(x) ((x) >> 6)

/* PP_SelfST */
#define T3VActive  0x0040
#define INITD   0x0080
#define SIBUSY   0x0100
#define EEPROMpresent 0x0200
#define EEPROMOK  0x0400
#define ELpresent  0x0800
#define EEsize   0x1000

/* PP_EEPROMCommand */
#define EEWriteEnable   0x00F0
#define EEWriteDisable  0x0000
#define EEWriteRegister 0x0100
#define EEReadRegister 0x0200
#define EEEraseRegister 0x0300
#define ELSEL   0x0400

#endif /* #ifndef CS8900_H */

//drivers/net/arm/cs8900.c

/*
 * linux/drivers/net/cs8900.c
 *
 * Author: Abraham van der Merwe <abraham at 2d3d.co.za>
 *
 * A Cirrus Logic CS8900A driver for Linux
 * based on the cs89x0 driver written by Russell Nelson,
 * Donald Becker, and others.
 *
 * This source code is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * version 2 as published by the Free Software Foundation.
 *
 * History:
 *    22-May-2002  Initial version (Abraham vd Merwe)
 *    30-May-2002  Added char device support for eeprom (Frank Becker)
 *    24-Jan-2004  Fixups for 2.6 (Frank Becker)
 *   15-July-2004 Modified for SMDK2410 (Roc Wu pwu at jadechip.com)
 */
 
#define VERSION_STRING "Cirrus Logic CS8900A driver for Linux (Modified for SMDK2410)"

/*
 * At the moment the driver does not support memory mode operation.
 * It is trivial to implement this, but not worth the effort.
 */

/*
 * TODO:
 *
 *   1. Sort out ethernet checksum
 *   2. If !ready in send_start(), queue buffer and send it in interrupt handler
 *      when we receive a BufEvent with Rdy4Tx, send it again. dangerous!
 *   3. how do we prevent interrupt handler destroying integrity of get_stats()?
 *   4. Change reset code to check status.
 *   5. Implement set_mac_address and remove fake mac address
 *   7. Link status detection stuff
 *   8. Write utility to write EEPROM, do self testing, etc.
 *   9. Implement DMA routines (I need a board w/ DMA support for that)
 *  10. Power management
 *  11. Add support for multiple ethernet chips
 */


#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/version.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/ioport.h>
#include <linux/pm.h>
#include <linux/irq.h>
#include <asm/hardware.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/fs.h>

// Added BSt
#include <asm/mach-types.h>

 

#ifdef CONFIG_ARCH_SMDK2410
#include "asm/arch-s3c2410/regs-irq.h"
#include "asm/arch/regs-mem.h"
//#include "asm/arch/smdk2410.h"
#include "asm/plat-s3c24xx/common-smdk.h"
#endif

#include "cs8900.h"

//#define FULL_DUPLEX
//#define DEBUG

typedef struct {
 struct net_device_stats stats;
 u16 txlen;
 int char_devnum;

        spinlock_t lock;
} cs8900_t;

int cs8900_probe (struct net_device *dev);
static struct net_device *cs8900_dev ;


/*
 * There seems to be no way to determine the exact size of the eeprom,
 * so we use the largest size.
 * FIXME: Verify it's safe to read/write past the end of a 64/128
 *        byte eeprom.
 *
 * Possible eeprom sizes:
 * Cx46 -  64 bytes
 * Cx56 - 128 bytes
 * Cx66 - 256 bytes
 */
#define MAX_EEPROM_SIZE  256

 

/*
 * I/O routines
 */

static inline u16 cs8900_read (struct net_device *dev,u16 reg)
{
 outw (reg,dev->base_addr + PP_Address);
 return (inw (dev->base_addr + PP_Data));
}

static inline void cs8900_write (struct net_device *dev,u16 reg,u16 value)
{
 outw (reg,dev->base_addr + PP_Address);
 outw (value,dev->base_addr + PP_Data);
}

static inline void cs8900_set (struct net_device *dev,u16 reg,u16 value)
{
 cs8900_write (dev,reg,cs8900_read (dev,reg) | value);
}

static inline void cs8900_clear (struct net_device *dev,u16 reg,u16 value)
{
 cs8900_write (dev,reg,cs8900_read (dev,reg) & ~value);
}

static inline void cs8900_frame_read (struct net_device *dev,struct sk_buff *skb,u16 length)
{
 insw (dev->base_addr,skb_put (skb,length),(length + 1) / 2);
}

static inline void cs8900_frame_write (struct net_device *dev,struct sk_buff *skb)
{
 outsw (dev->base_addr,skb->data,(skb->len + 1) / 2);
}

/*
 * Debugging functions
 */

#ifdef DEBUG
static inline int printable (int c)
{
 return ((c >= 32 && c <= 126) ||
   (c >= 174 && c <= 223) ||
   (c >= 242 && c <= 243) ||
   (c >= 252 && c <= 253));
}

static void dump16 (struct net_device *dev,const u8 *s,size_t len)
{
 int i;
 char str[128];

 if (!len) return;

 *str = '\0';

 for (i = 0; i < len; i++) {
  if (i && !(i % 4)) strcat (str," ");
  sprintf (str,"%s%.2x ",str,s[i]);
 }

 for ( ; i < 16; i++) {
  if (i && !(i % 4)) strcat (str," ");
  strcat (str,"   ");
 }

 strcat (str," ");
 for (i = 0; i < len; i++) sprintf (str,"%s%c",str,printable (s[i]) ? s[i] : '.');

 printk (KERN_DEBUG "%s:     %s\n",dev->name,str);
}

static void hexdump (struct net_device *dev,const void *ptr,size_t size)
{
 const u8 *s = (u8 *) ptr;
 int i;
 for (i = 0; i < size / 16; i++, s += 16) dump16 (dev,s,16);
 dump16 (dev,s,size % 16);
}

static void dump_packet (struct net_device *dev,struct sk_buff *skb,const char *type)
{
 printk (KERN_INFO "%s: %s %d byte frame %.2x:%.2x:%.2x:%.2x:%.2x:%.2x to %.2x:%.2x:%.2x:%.2x:%.2x:%.2x type %.4x\n",
   dev->name,
   type,
   skb->len,
   skb->data[0],skb->data[1],skb->data[2],skb->data[3],skb->data[4],skb->data[5],
   skb->data[6],skb->data[7],skb->data[8],skb->data[9],skb->data[10],skb->data[11],
   (skb->data[12] << 8) | skb->data[13]);
 if (skb->len < 0x100) hexdump (dev,skb->data,skb->len);
}


#endif /* #ifdef DEBUG */

/*
 * Driver functions
 */

static void cs8900_receive (struct net_device *dev)
{
 cs8900_t *priv = (cs8900_t *) dev->priv;
 struct sk_buff *skb;
 u16 status,length;

 status = cs8900_read (dev,PP_RxStatus);
 length = cs8900_read (dev,PP_RxLength);

 if (!(status & RxOK)) {
  priv->stats.rx_errors++;
  if ((status & (Runt | Extradata))) priv->stats.rx_length_errors++;
  if ((status & CRCerror)) priv->stats.rx_crc_errors++;
  return;
 }

 if ((skb = dev_alloc_skb (length + 4)) == NULL) {
  priv->stats.rx_dropped++;
  return;
 }

 skb->dev = dev;
 skb_reserve (skb,2);

 cs8900_frame_read (dev,skb,length);

#ifdef FULL_DUPLEX
 dump_packet (dev,skb,"recv");
#endif /* #ifdef FULL_DUPLEX */

 skb->protocol = eth_type_trans (skb,dev);

 netif_rx (skb);
 dev->last_rx = jiffies;

 priv->stats.rx_packets++;
 priv->stats.rx_bytes += length;
}

static int cs8900_send_start (struct sk_buff *skb,struct net_device *dev)
{
 cs8900_t *priv = (cs8900_t *) dev->priv;
 u16 status;

 spin_lock_irq(&priv->lock);
 netif_stop_queue (dev);

 cs8900_write (dev,PP_TxCMD,TxStart (After5));
 cs8900_write (dev,PP_TxLength,skb->len);

 status = cs8900_read (dev,PP_BusST);

 if ((status & TxBidErr)) {
  spin_unlock_irq(&priv->lock);
  printk (KERN_WARNING "%s: Invalid frame size %d!\n",dev->name,skb->len);
  priv->stats.tx_errors++;
  priv->stats.tx_aborted_errors++;
  priv->txlen = 0;
  return (1);
 }

 if (!(status & Rdy4TxNOW)) {
  spin_unlock_irq(&priv->lock);
  printk (KERN_WARNING "%s: Transmit buffer not free!\n",dev->name);
  priv->stats.tx_errors++;
  priv->txlen = 0;
  /* FIXME: store skb and send it in interrupt handler */
  return (1);
 }

 cs8900_frame_write (dev,skb);
 spin_unlock_irq(&priv->lock);

#ifdef DEBUG
 dump_packet (dev,skb,"send");
#endif /* #ifdef DEBUG */

 dev->trans_start = jiffies;

 dev_kfree_skb (skb);

 priv->txlen = skb->len;

 return (0);
}

static irqreturn_t cs8900_interrupt (int irq,void *id)
{
 struct net_device *dev = (struct net_device *) id;
 cs8900_t *priv;
 volatile u16 status;
  irqreturn_t handled = 0;


 if (dev->priv == NULL) {
  printk (KERN_WARNING "%s: irq %d for unknown device.\n",dev->name,irq);
  return 0;
 }

 priv = (cs8900_t *) dev->priv;
 
 while ((status = cs8900_read (dev, PP_ISQ))) {
  handled = 1;
  switch (RegNum (status)) {
  case RxEvent:
   cs8900_receive (dev);
   break;

  case TxEvent:
   priv->stats.collisions += ColCount (cs8900_read (dev,PP_TxCOL));
   if (!(RegContent (status) & TxOK)) {
    priv->stats.tx_errors++;
    if ((RegContent (status) & Out_of_window)) priv->stats.tx_window_errors++;
    if ((RegContent (status) & Jabber)) priv->stats.tx_aborted_errors++;
    break;
   } else if (priv->txlen) {
    priv->stats.tx_packets++;
    priv->stats.tx_bytes += priv->txlen;
   }
   priv->txlen = 0;
   netif_wake_queue (dev);
   break;

  case BufEvent:
   if ((RegContent (status) & RxMiss)) {
    u16 missed = MissCount (cs8900_read (dev,PP_RxMISS));
    priv->stats.rx_errors += missed;
    priv->stats.rx_missed_errors += missed;
   }
   if ((RegContent (status) & TxUnderrun)) {
    priv->stats.tx_errors++;
    priv->stats.tx_fifo_errors++;

    priv->txlen = 0;
    netif_wake_queue (dev);
   }
   /* FIXME: if Rdy4Tx, transmit last sent packet (if any) */
   break;

  case TxCOL:
   priv->stats.collisions += ColCount (cs8900_read (dev,PP_TxCOL));
   break;

  case RxMISS:
   status = MissCount (cs8900_read (dev,PP_RxMISS));
   priv->stats.rx_errors += status;
   priv->stats.rx_missed_errors += status;
   break;
  }
 }
 return IRQ_RETVAL(handled);
}

static void cs8900_transmit_timeout (struct net_device *dev)
{
 cs8900_t *priv = (cs8900_t *) dev->priv;
 priv->stats.tx_errors++;
 priv->stats.tx_heartbeat_errors++;
 priv->txlen = 0;
 netif_wake_queue (dev);
}

static int cs8900_start (struct net_device *dev)
{
 int result;

 set_irq_type(dev->irq, IRQT_RISING);

 /* enable the ethernet controller */
 cs8900_set (dev,PP_RxCFG,RxOKiE | BufferCRC | CRCerroriE | RuntiE | ExtradataiE);
 cs8900_set (dev,PP_RxCTL,RxOKA | IndividualA | BroadcastA);
 cs8900_set (dev,PP_TxCFG,TxOKiE | Out_of_windowiE | JabberiE);
 cs8900_set (dev,PP_BufCFG,Rdy4TxiE | RxMissiE | TxUnderruniE | TxColOvfiE | MissOvfloiE);
 cs8900_set (dev,PP_LineCTL,SerRxON | SerTxON);
 cs8900_set (dev,PP_BusCTL,EnableRQ);

#ifdef FULL_DUPLEX
 cs8900_set (dev,PP_TestCTL,FDX);
#endif /* #ifdef FULL_DUPLEX */
 udelay(200); 
 /* install interrupt handler */
 if ((result = request_irq (dev->irq, &cs8900_interrupt, 0, dev->name, dev)) < 0) {
  printk (KERN_ERR "%s: could not register interrupt %d\n",dev->name, dev->irq);
  return (result);
 }
 
 /* start the queue */
 netif_start_queue (dev);

 return (0);
}

static int cs8900_stop (struct net_device *dev)
{
 /* disable ethernet controller */
 cs8900_write (dev,PP_BusCTL,0);
 cs8900_write (dev,PP_TestCTL,0);
 cs8900_write (dev,PP_SelfCTL,0);
 cs8900_write (dev,PP_LineCTL,0);
 cs8900_write (dev,PP_BufCFG,0);
 cs8900_write (dev,PP_TxCFG,0);
 cs8900_write (dev,PP_RxCTL,0);
 cs8900_write (dev,PP_RxCFG,0);

 /* uninstall interrupt handler */
 free_irq (dev->irq,dev);

 /* stop the queue */
 netif_stop_queue (dev);

 return (0);
}

static struct net_device_stats *cs8900_get_stats (struct net_device *dev)
{
 cs8900_t *priv = (cs8900_t *) dev->priv;
 return (&priv->stats);
}

static void cs8900_set_receive_mode (struct net_device *dev)
{
 if ((dev->flags & IFF_PROMISC))
  cs8900_set (dev,PP_RxCTL,PromiscuousA);
 else
  cs8900_clear (dev,PP_RxCTL,PromiscuousA);

 if ((dev->flags & IFF_ALLMULTI) && dev->mc_list)
  cs8900_set (dev,PP_RxCTL,MulticastA);
 else
  cs8900_clear (dev,PP_RxCTL,MulticastA);
}

 

 

/*
 * Driver initialization routines
 */

int __init cs8900_probe (struct net_device *dev)
{
 static cs8900_t priv;
 int i,result;
 u16 value;

 printk (VERSION_STRING"\n");

 memset (&priv,0,sizeof (cs8900_t));

 //+kevin
// __raw_writel(0x2211d110,S3C2410_BWSCON);
// __raw_writel(0x1f7c,S3C2410_BANKCON3);

 

#if defined(CONFIG_ARCH_SMDK2410)
 dev->dev_addr[0] = 0x00;
 dev->dev_addr[1] = 0x00;
 dev->dev_addr[2] = 0x3e;
 dev->dev_addr[3] = 0x26;
 dev->dev_addr[4] = 0x0a;
 dev->dev_addr[5] = 0x00;

#endif

 dev->if_port   = IF_PORT_10BASET;
 dev->priv      = (void *) &priv;

 spin_lock_init(&priv.lock);

 //hejiasheng SET_MODULE_OWNER (dev);

 

 

#if defined(CONFIG_ARCH_SMDK2410)
 dev->base_addr = vSMDK2410_ETH_IO + 0x300;
 dev->irq = IRQ_EINT9;
#endif /* #if defined(CONFIG_ARCH_SMDK2410) */

 

 if ((result = check_mem_region (dev->base_addr, 16))) {
  printk (KERN_ERR "%s: can't get I/O port address 0x%lx\n",dev->name,dev->base_addr);
  return (result);
 }
 request_mem_region (dev->base_addr, 16, dev->name);
 
     /* verify EISA registration number for Cirrus Logic */
 if ((value = cs8900_read (dev,PP_ProductID)) != EISA_REG_CODE) {
  printk (KERN_ERR "%s: incorrect signature 0x%.4x\n",dev->name,value);
  return (-ENXIO);
 }

 /* verify chip version */
 value = cs8900_read (dev,PP_ProductID + 2);
 if (VERSION (value) != CS8900A) {
  printk (KERN_ERR "%s: unknown chip version 0x%.8x\n",dev->name,VERSION (value));
  return (-ENXIO);
 }
 /* setup interrupt number */
 cs8900_write (dev,PP_IntNum,0);


 printk (KERN_INFO "%s: CS8900A rev %c at %#lx irq=%d",
  dev->name,'B' + REVISION (value) - REV_B, dev->base_addr, dev->irq);

 for (i = 0; i < ETH_ALEN; i += 2)
  cs8900_write (dev,PP_IA + i,dev->dev_addr[i] | (dev->dev_addr[i + 1] << 8));

 printk (", addr:");
 for (i = 0; i < ETH_ALEN; i += 2)
 {
  u16 mac = cs8900_read (dev,PP_IA + i);
  printk ("%c%02X:%2X", (i==0)?' ':':', mac & 0xff, (mac >> 8));
 }
 printk ("\n");

 return (0);
}

static int __init cs8900_init (void)
{
 struct net_device *ndev;

        ndev = alloc_etherdev(sizeof (cs8900_t));
        if (!ndev) {
                printk("%s: could not allocate device.\n", "cs8900");
                return -ENOMEM;
        }

 cs8900_dev = ndev;
 cs8900_dev->init = cs8900_probe;
 ether_setup (ndev);

 ndev->open               = cs8900_start;
 ndev->stop               = cs8900_stop;
 ndev->hard_start_xmit    = cs8900_send_start;
 ndev->get_stats          = cs8900_get_stats;
 ndev->set_multicast_list = cs8900_set_receive_mode;
 ndev->tx_timeout         = cs8900_transmit_timeout;
 ndev->watchdog_timeo     = HZ;

 

 return (register_netdev (cs8900_dev));
}

static void __exit cs8900_cleanup (void)
{
 cs8900_t *priv = (cs8900_t *) cs8900_dev->priv;
 if( priv->char_devnum)
 {
  unregister_chrdev(priv->char_devnum,"cs8900_eeprom");
 }
 release_mem_region (cs8900_dev->base_addr,16);
 unregister_netdev (cs8900_dev);
}

MODULE_AUTHOR ("Abraham van der Merwe <abraham at 2d3d.co.za>");
MODULE_DESCRIPTION (VERSION_STRING);
MODULE_LICENSE ("GPL");

module_init (cs8900_init);
module_exit (cs8900_cleanup);

#26 VMWare/Linux/Ubuntu/Fedora/CentOS/U-BOOT » 添加LTV350QV的FB驱动到基于linux-2.6.26的GEC2440开发板 --缥缈九哥 » 2020-05-09 21:01:13

缥缈九哥
回复: 0

添加LTV350QV的FB驱动到基于linux-2.6.26的GEC2440开发板

1,编译配置内核
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26-9g24x0# make menuconfig
进入配置菜单添加驱动到内核:
Device Drivers  --->
    Graphics support  ---> 
<*> Support for frame buffer devices  --->
<*>   S3C2410 LCD framebuffer support

2,修改arch/arm/mach-s3c2440/mach-smdk2440.c文件
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26-9g24x0# vi arch/arm/mach-s3c2440/mach-smdk2440.c
把static struct s3c2410fb_display smdk2440_lcd_cfg __initdata 修改成:
// change by yuanxihua@21cn.com
static struct s3c2410fb_display smdk2440_lcd_cfg __initdata = {

  .lcdcon5 = S3C2410_LCDCON5_FRM565  |
     S3C2410_LCDCON5_INVVCLK  |
       S3C2410_LCDCON5_INVVLINE  |
     S3C2410_LCDCON5_INVVFRAME  |
//      S3C2410_LCDCON5_INVVD  |
//    S3C2410_LCDCON5_INVVDEN  |
//      S3C2410_LCDCON5_PWREN   |
//      S3C2410_LCDCON5_BSWP  |
       S3C2410_LCDCON5_HWSWP,

  .type  = S3C2410_LCDCON1_TFT,

  .width  = 320,
  .height  = 240,

  .pixclock = 270000, /* HCLK 60 MHz, divisor 10 */
  .xres  = 320,
  .yres  = 240,
  .bpp  = 16,
  .left_margin = 21,
  .right_margin = 14,
  .hsync_len  = 19,
  .upper_margin = 6,
  .lower_margin = 5,
  .vsync_len  = 4,
};

把static struct s3c2410fb_mach_info smdk2440_fb_info __initdata修改成:
// change by yuanxihua@21cn.com
  static struct s3c2410fb_mach_info smdk2440_fb_info __initdata = {
  .displays = &smdk2440_lcd_cfg,
  .num_displays = 1,
  .default_display = 0,

#if 1
  /* currently setup by downloader */
  .gpccon   = 0xaa9556a9,
  .gpccon_mask = 0xffffffff,
  .gpcup   = 0xffffffff,
  .gpcup_mask  = 0xffffffff,
  .gpdcon   = 0xaaaaaaaa,
  .gpdcon_mask = 0xffffffff,
  .gpdup   = 0xffffffff,
  .gpdup_mask  = 0xffffffff,
#endif

  .lpcsel   = 0,
};
把s3c24xx_init_clocks(16934400);修改成:
// s3c24xx_init_clocks(16934400);  // change by yuanxihua@21cn.com
s3c24xx_init_clocks(12000000);

3,修改include/asm-arm/arch-s3c2410/regs-lcd.h文件
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26-9g24x0# vi include/asm-arm/arch-s3c2410/regs-lcd.h
把#define S3C2410_LCDCON1_MMODE    (1<<7)修改成:
//#define S3C2410_LCDCON1_MMODE    (1<<7)
#define S3C2410_LCDCON1_MMODE    (0<<7)   // change by yuanxihua@21cn.com

4,修改drivers/video/s3c2410fb.c文件
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26-9g24x0# vi drivers/video/s3c2410fb.c
在第51行的/* useful functions */后添加:

 /************************************************/
 //LTV350QV_FOE_V0.0
 
 #define LTV350QV_FOE       0x1d   //device ID
 
 typedef struct _LTV350qv_spi_data_{
  unsigned char    Device_ID;   //ID of the device
  unsigned int   Index;    //index of register
  unsigned long   Structure;  //structure to be writed
 }LTV350QV_SPI_Data;
 
 //micro for LTV350QV_FOE
 #define CS_H     __raw_writel(__raw_readl(S3C2410_GPCDAT) |(1<< 8), S3C2410_GPCDAT)//MAKE_HIGH(LTV350QV_CS)
 #define CS_L     __raw_writel(__raw_readl(S3C2410_GPCDAT)&~(1<< 8), S3C2410_GPCDAT)//MAKE_LOW(LTV350QV_CS)
 #define SCLK_H   __raw_writel(__raw_readl(S3C2410_GPCDAT) |(1<< 9), S3C2410_GPCDAT)//MAKE_HIGH(LTV350QV_SCL)
 #define SCLK_L   __raw_writel(__raw_readl(S3C2410_GPCDAT)&~(1<< 9), S3C2410_GPCDAT)//MAKE_LOW(LTV350QV_SCL)
 #define SDI_H    __raw_writel(__raw_readl(S3C2410_GPCDAT) |(1<<10), S3C2410_GPCDAT)//MAKE_HIGH(LTV350QV_SDI)
 #define SDI_L    __raw_writel(__raw_readl(S3C2410_GPCDAT)&~(1<<10), S3C2410_GPCDAT)//MAKE_LOW(LTV350QV_SDI)
 #define RST_H    __raw_writel(__raw_readl(S3C2410_GPDDAT) |(1<< 0), S3C2410_GPDDAT)//MAKE_HIGH(LTV350QV_RST)
 #define RST_L    __raw_writel(__raw_readl(S3C2410_GPDDAT)&~(1<< 0), S3C2410_GPDDAT)//MAKE_LOW(LTV350QV_RST)
 
 //***************************************************************
 //**********these functions for SUMSUN LTV350QV TFT LCD****************
 //***************************************************************
 static void LTV350QV_Short_Delay(u_char time)
 {
  ndelay(150);
 }
 /*
 static void LTV350QV_Rst(void)
 {
  RST_L;
  mdelay(1);
  RST_H;
  mdelay(1);
 }
 */
 static void LTV350QV_Register_Write(LTV350QV_SPI_Data regdata)
 {
  u_char i,temp1;
  u_int temp2;
  u_long temp3;
  unsigned long flags;           
 
  //write index
  temp1=regdata.Device_ID<<2 | 0<<1 | 0<<0;  //register index
  temp2=regdata.Index;
  temp3=(temp1<<24) | (temp2<<8);
 
  local_irq_save(flags);
  
  CS_L;
  LTV350QV_Short_Delay(1);
  for(i=0;i<24;i++)
   {
    SCLK_L;
    if(temp3 & (1<<(31-i)) )   //if is H
     SDI_H;
    else
     SDI_L;
    LTV350QV_Short_Delay(1);   //setup time
    SCLK_H;
    LTV350QV_Short_Delay(1);   //hold time
   }
  CS_H;
  
  LTV350QV_Short_Delay(5);
  
  //write instruction
  temp1=regdata.Device_ID<<2 | 1<<1 | 0<<0; //instruction
  temp2=regdata.Structure;
  temp3=(temp1<<24) | (temp2<<8);
  
  CS_L;
  LTV350QV_Short_Delay(1);
  for(i=0;i<24;i++)
   {
    SCLK_L;
    if(temp3 & (1<<(31-i)) )   //if is H
     SDI_H;
    else
     SDI_L;
    LTV350QV_Short_Delay(1);
    SCLK_H;
    LTV350QV_Short_Delay(1);
   }
  CS_H;
 
  local_irq_restore(flags);
 }
 /****************************************
 *  *
 ****************************************/
 static void LTV350QV_Write(u_int index, u_int regdata)
 {
  LTV350QV_SPI_Data WriteData;
  
  WriteData.Device_ID = LTV350QV_FOE;
  WriteData.Index  = index;
  WriteData.Structure = regdata;
 
  LTV350QV_Register_Write(WriteData);
 }
 /****************************************
 *  *power ON sequence
 ****************************************/
 static void LTV350QV_Power_ON(void)
 { 
   LTV350QV_Write( 9, 0x0000);
   mdelay(150);
   LTV350QV_Write( 9, 0x4000);
   LTV350QV_Write(10, 0x2000);
   LTV350QV_Write( 9, 0x4055);
   mdelay(550);
   LTV350QV_Write( 1, 0x409d);
   LTV350QV_Write( 2, 0x0204);
  LTV350QV_Write( 3, 0x0100);
   LTV350QV_Write( 4, 0x3000);
   LTV350QV_Write( 5, 0x4003);
   LTV350QV_Write( 6, 0x000a);
   LTV350QV_Write( 7, 0x0021);
   LTV350QV_Write( 8, 0x0c00);
   LTV350QV_Write(10, 0x0103);
  LTV350QV_Write(11, 0x0301);
   LTV350QV_Write(12, 0x1f0f);
   LTV350QV_Write(13, 0x1f0f);
   LTV350QV_Write(14, 0x0707);
   LTV350QV_Write(15, 0x0307);
   LTV350QV_Write(16, 0x0707);
   LTV350QV_Write(17, 0x0000);
   LTV350QV_Write(18, 0x0004);
   LTV350QV_Write(19, 0x0000);
 
   mdelay(200);
   LTV350QV_Write( 9, 0x4a55);
   LTV350QV_Write( 5, 0x5003);
 }
 
 /**********************************
 *  *power OFF sequence
 **********************************/
 /*static void LTV350QV_Powen_OFF(void)
 {
  LTV350QV_Write( 9, 0x4055);// GON -> 0, POC -> 0
  LTV350QV_Write( 5, 0x4003);// DSC -> 0
   LTV350QV_Write(10, 0x0000);// VCOMG -> 0
   mdelay(20);
  LTV350QV_Write( 9, 0x4000);// AP[2:0] -> 000
 }*/
 static void s3c2440fb_init_ltv350qv(void)
 {
  __raw_writel(0xaa9556a9, S3C2410_GPCCON);  //Initialize VD[7:0],LCDVF[2:0],VM,VFRAME,VLINE,VCLK,LEND
              //LCDVF[0],[1],[2]---output;VD[0],[1],[2]----output.            
  __raw_writel(0xffffffff, S3C2410_GPCUP);   // Disable Pull-up register
    LTV350QV_Power_ON() ;     //init LCD model
  __raw_writel(0xaaaaaaaa, S3C2410_GPDCON);
  __raw_writel(0xffffffff, S3C2410_GPDUP);
 // __raw_writel(3, S3C2410_LCDINTMSK);    // MASK LCD Sub Interrupt
 // __raw_writel(0, S3C2410_TPAL);     // Disable Temp Palette
 // __raw_writel(0, S3C2410_LPCSEL);    // Disable LPC3600
 }
 
 

在static int s3c2410fb_init_registers(struct fb_info *info)的 return 0;前添加:
s3c2440fb_init_ltv350qv();

5, 编译内核生成驱动
root@yuanxh-desktop:/home/yuanxh/s3c2410/linux-2.6.26-9g24x0# make

#27 VMWare/Linux/Ubuntu/Fedora/CentOS/U-BOOT » 添加XMODEM下载协议到基于u-boot-1.3.4的9G9260开发板 --缥缈九哥 » 2020-05-09 20:59:33

缥缈九哥
回复: 0

添加XMODEM下载协议到基于u-boot-1.3.4的9G9260开发板

1,下载解压源码:
root@yuanxh-desktop:/home/yuanxh/sam9260# wget ftp://ftp.denx.de/pub/u-boot/u-boot-1.3.4.tar.bz2
root@yuanxh-desktop:/home/yuanxh/sam9260# wget ftp://www.linux4sam.org/pub/uboot/u-boot-1.3.4-exp/u-boot-1.3.4-exp.diff
root@yuanxh-desktop:/home/yuanxh/sam9260# tar xjvf u-boot-1.3.4.tar.bz2
root@yuanxh-desktop:/home/yuanxh/sam9260# mv u-boot-1.3.4 u-boot-1.3.4-9g9260
root@yuanxh-desktop:/home/yuanxh/sam9260# mv u-boot-1.3.4-exp.diff u-boot-1.3.4-9g9260/

2,打补丁:
root@yuanxh-desktop:/home/yuanxh/sam9260# cd u-boot-1.3.4-9g9260
root@yuanxh-desktop:/home/yuanxh/sam9260/u-boot-1.3.4-9g9260# patch -p1 < ./u-boot-1.3.4-exp.diff

3,默认配置:
root@yuanxh-desktop:/home/yuanxh/sam9260/u-boot-1.3.4-9g9260# make at91sam9260ek_dataflash_cs0_config
root@yuanxh-desktop:/home/yuanxh/sam9260/u-boot-1.3.4-9g9260# make at91sam9260ek_dataflash_cs1_config
root@yuanxh-desktop:/home/yuanxh/sam9260/u-boot-1.3.4-9g9260# make at91sam9260ek_nandflash_config
(选择对应的一项,区分NANDFLASH和DATAFLASH的CS0,CS1)

4,添加XMODEM下载协议
在\common\Makefile的147行添加 COBJS-y += cmd_xmodem.o xmodem.o
root@yuanxh-desktop:/home/yuanxh/sam9260/u-boot-1.3.4-9g9260# vi common/Makefile
在\common\中增加源文件  xmodem.c cmd_xmodem.c
root@yuanxh-desktop:/home/yuanxh/sam9260/u-boot-1.3.4-9g9260# rz
root@yuanxh-desktop:/home/yuanxh/sam9260/u-boot-1.3.4-9g9260# mv xmodem.c cmd_xmodem.c common/

5,编译发布:
root@yuanxh-desktop:/home/yuanxh/sam9260/u-boot-1.3.4-9g9260# make
root@yuanxh-desktop:/home/yuanxh/sam9260/u-boot-1.3.4-9g9260# mv u-boot.bin u-boot-1.3.4-9g9260.bin
root@yuanxh-desktop:/home/yuanxh/sam9260/u-boot-1.3.4-9g9260# sz u-boot-1.3.4-9g9260.bin

6, 清除配置
root@yuanxh-desktop:/home/yuanxh/sam9260/u-boot-1.3.4-9g9260# make distclean

附件:xmodem.c文件

/*******************************************************************************
 *
 * Filename: xmodem.c
 *
 * change from KB9202 , yuanxihua@21cn.com
 ******************************************************************************/

#include <common.h>

extern int xmodem_rx(char *dest);

/* Line control codes */
#define SOH   0x01 /* start of header for Xmodem protocol  */
#define STX   0x02 /* start of header for 1K xmodem protocol*/
#define ACK   0x06 /* Acknowledge */
#define NAK   0x15 /* Negative acknowledge */
#define CAN   0x18 /* Cancel */
#define EOT   0x04 /* end of text */
#define TIMEOUT 2
#define TIMEOUT_LONG 10
#define XMODEM_DATA_SIZE_SOH 128  /* for Xmodem protocol */
#define XMODEM_DATA_SIZE_STX 1024 /* for 1K xmodem protocol */

enum {
 INVALID_STATE = 0,
 WAITING_START,
 WAIT_HEAD,
 RX_PACKET,
 RX_EOT,
 SEND_NAK
};

static char packetNumber;
static int PACKET_SIZE;
static char HEAD;

#define TransitionState(x, y) (x = y)

void DebugPutc(char cValue)
{
 putc (cValue & 0x1FF);
}
int WaitForChar(char *cPtr, int seconds)
{
   unsigned long counter = 0;
   
   seconds = seconds * 1000 ;  /* delay 1000 * 50 * 20us */
   
   while (!tstc () && (counter < seconds * 50 ))
    {
      udelay (20);
      counter++;
    }
  if (tstc ())
    {
      *cPtr = getc ();
      return 1;
    }
  return 0;
}
static int GetRecord(char blocknum, char *dest) {
 int  size;
 char  nextChar;
 unsigned chk, j;

 chk = 0;

 if (!WaitForChar(&nextChar, TIMEOUT)) {
  return (0);
 }

 if ((char)nextChar != (char)~blocknum) {
  return (0);
 }

 for (size = 0; size < PACKET_SIZE; ++size) {
  if (!WaitForChar(&nextChar, TIMEOUT)) {
   return (0);
  }
  chk = chk ^(int)nextChar << 8;
  for (j = 0; j < 8; ++j) {
   if (chk & 0x8000)
    chk = chk << 1 ^ 0x1021;
   else
    chk = chk << 1;
  }
  *dest++ = nextChar;
 }

 chk &= 0xFFFF;

 if ((!WaitForChar(&nextChar, TIMEOUT)) || (nextChar != ((chk >> 8) & 0xFF))) {
  return (0);
 }

 if ((!WaitForChar(&nextChar, TIMEOUT)) || (nextChar != (chk & 0xFF))) {
  return (0);
 }

 DebugPutc(ACK);

 return (1);
}
int xmodem_rx(char *dest) {

 int  state;
 char  nextChar, *startAddress = dest;

 packetNumber = 1;
 state = WAITING_START;
 PACKET_SIZE = XMODEM_DATA_SIZE_SOH;
 HEAD = SOH;
      
 while (1) {

  if (state == WAITING_START) {
   DebugPutc('C');
   if (WaitForChar(&nextChar, TIMEOUT)) {
    if (nextChar == SOH)
    {
      PACKET_SIZE = XMODEM_DATA_SIZE_SOH;
      HEAD = SOH;
      TransitionState(state, RX_PACKET);
    }
    else
    if (nextChar == STX)
    {
      PACKET_SIZE = XMODEM_DATA_SIZE_STX;
      HEAD = STX;
      TransitionState(state, RX_PACKET);
    }
   }
  }

  if (state == WAIT_HEAD) {
   if (!WaitForChar(&nextChar, TIMEOUT_LONG)) {
    return (-1);
   }

/*   if (nextChar == HEAD) {
    TransitionState(state, RX_PACKET);
   }
*/
    if (nextChar == SOH)
    {
      PACKET_SIZE = XMODEM_DATA_SIZE_SOH;
      HEAD = SOH;
      TransitionState(state, RX_PACKET);
    }
    else
    if (nextChar == STX)
    {
      PACKET_SIZE = XMODEM_DATA_SIZE_STX;
      HEAD = STX;
      TransitionState(state, RX_PACKET);
    }
    
   if (nextChar == EOT) {
    // TransitionState(state, RX_EOT);
    DebugPutc(ACK);
    return (dest - startAddress);
   }
  }

  if (state == RX_PACKET) {
   if (!WaitForChar(&nextChar, TIMEOUT)) {
    return (-1);
   }

   if (nextChar != packetNumber) {
    // TransitionState(state, SEND_NAK);
    DebugPutc(NAK);
    return (-1);
   }

   if (GetRecord(packetNumber, dest)) {
    dest += PACKET_SIZE;
    ++packetNumber;
    TransitionState(state, WAIT_HEAD);
   } else {
    return (-1);
   }
  }
 }

 // the loop above should return in all cases
 return (-1);
}

附件:cmd_xmodem.c文件

#include <common.h>
#include <command.h>
#include <asm/io.h>
#include <asm/arch/hardware.h>

static ulong load_xmodem_bin(ulong *);
static char *bin_start_address;

int do_xmodem(cmd_tbl_t *cmdtp,int flag,int argc, char *argv[])
{
 DECLARE_GLOBAL_DATA_PTR;

 ulong offset = 0;
 ulong addr;
 int load_baudrate, current_baudrate;
 int rcode = 0;
 char *s;

 /* pre-set offset from CFG_LOAD_ADDR */
 offset = CFG_LOAD_ADDR;

 /* pre-set offset from $loadaddr */
 if ((s = getenv("loadaddr")) != NULL) {
  offset = simple_strtoul(s, NULL, 16);
 }

 load_baudrate = current_baudrate = gd->baudrate;

 if (argc >= 2) {
  offset = simple_strtoul(argv[1], NULL, 16);
 }
 if (argc == 3) {
  load_baudrate = (int)simple_strtoul(argv[2], NULL, 10);

  /* default to current baudrate */
  if (load_baudrate == 0)
   load_baudrate = current_baudrate;
 }

 if (load_baudrate != current_baudrate) {
  printf ("## Switch baudrate to %d bps and press ENTER ...\n",
   load_baudrate);
  udelay(50000);
  gd->baudrate = load_baudrate;
  serial_setbrg ();
  udelay(50000);
  for (;;) {
   if (getc() == '\r')
    break;
  }
 }

 printf ("## Ready for binary (xmodem) download "
  "to 0x%08lX at %d bps...\n",
  offset,
  load_baudrate);

 addr = load_xmodem_bin((ulong *) offset);
 
 if (addr == ~0) {
  load_addr = 0;
  printf ("## Binary (xmodem) download aborted\n");
  rcode = 1;
 } else {
  printf ("## Start Addr      = 0x%08lX\n", addr);
  load_addr = addr;
 }

 if (load_baudrate != current_baudrate) {
  printf ("## Switch baudrate to %d bps and press ESC ...\n",
   current_baudrate);
  udelay (50000);
  gd->baudrate = current_baudrate;
  serial_setbrg ();
  udelay (50000);
  for (;;) {
   if (getc() == 0x1B) /* ESC */
    break;
  }
 }

#ifdef CONFIG_AUTOSCRIPT
 if (load_addr) {
  char *s;

  if (((s = getenv("autoscript")) != NULL) && (strcmp(s,"yes") == 0)) {
   printf("Running autoscript at addr 0x%08lX ...\n", load_addr);
   rcode = autoscript (load_addr);
  }
 }
#endif
 return rcode;
}

static ulong load_xmodem_bin(unsigned long *addr)
{
 int size, i;
 char buf[32];
 ulong offset;
 
// set_kerm_bin_mode ((ulong *) offset);
// size = k_recv ();
  offset = addr;
  bin_start_address = (char *) addr;
  size = xmodem_rx(bin_start_address);

 /*
  * Gather any trailing characters (for instance, the ^D which
  * is sent by 'cu' after sending a file), and give the
  * box some time (100 * 1 ms)
  */
 for (i=0; i<100; ++i) {
  if (tstc()) {
   (void) getc();
  }
  udelay(1000);
 }

 flush_cache (offset, size);

 printf("## Total Size      = 0x%08x = %d Bytes\n", size, size);
 sprintf(buf, "%X", size);
 setenv("filesize", buf);

 return offset;
}

U_BOOT_CMD(
  rx,    3,    0,     do_xmodem,
 "rx      - load binary file over serial line (xmodem)\n",
 "[ off ] [ baud ]\n"
 "    - load binary file over serial line"
 " with offset 'off' and baudrate 'baud'\n"
);

 

#28 VMWare/Linux/Ubuntu/Fedora/CentOS/U-BOOT » 移植linux-2.6.27到9G9260开发板 --缥缈九哥 » 2020-05-09 20:57:54

缥缈九哥
回复: 0

移植linux-2.6.27到9G9260开发板

1,下载解压源码:
root@yuanxh-desktop:/home/yuanxh/sam9260# wget http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.27.tar.bz2
root@yuanxh-desktop:/home/yuanxh/sam9260# wget http://maxim.org.za/AT91RM9200/2.6/2.6.27-at91.patch.gz
root@yuanxh-desktop:/home/yuanxh/sam9260# wget ftp://www.linux4sam.org/pub/linux/2.6.27-at91/2.6.27-at91-exp.patch.gz

2,打补丁:
root@yuanxh-desktop:/home/yuanxh/sam9260# tar xjvf linux-2.6.27.tar.bz2
root@yuanxh-desktop:/home/yuanxh/sam9260# gzip -d 2.6.27-at91.patch.gz
root@yuanxh-desktop:/home/yuanxh/sam9260# gzip -d 2.6.27-at91-exp.patch.gz
root@yuanxh-desktop:/home/yuanxh/sam9260# mv linux-2.6.27 linux-2.6.27-9g9260
root@yuanxh-desktop:/home/yuanxh/sam9260# mv 2.6.27-at91.patch 2.6.27-at91-exp.patch linux-2.6.27-9g9260/
root@yuanxh-desktop:/home/yuanxh/sam9260# cd linux-2.6.27-9g9260/
root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260# patch -p1 < ./2.6.27-at91.patch
root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260# patch -p1 < ./2.6.27-at91-exp.patch

3,修改Makefile
root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260# vi Makefile
  把第4行的EXTRAVERSION = 修改为 EXTRAVERSION =-9g9260
  把193行的ARCH           ?= $(SUBARCH) 修改为 ARCH           ?= arm
把194行的CROSS_COMPILE  ?= 修改为  CROSS_COMPILE  ?= arm-linux-

4,修改Kconfig
root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260# vi arch/arm/mach-at91/Kconfig
在第189行添加上:

config MACH_9G9260EK
bool "9G9260-EK Evaluation Kit"
depends on MACH_AT91SAM9260EK
help
   Select this if you are using yuanxihua's 9G9260EK Evaluation Kit
   <http://blog.163.com/yuan_xihua/>

5,默认配置:
root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260# make help
root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260# make at91sam9260ek_defconfig
root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260# make menuconfig
关闭掉这个选项

 Kernel Features  ---> 
 [*] Use the ARM EABI to compile the kernel
 修改启动命令行参数
 Boot options  --->   
  (mem=64M console=ttyS0,115200 initrd=0x21100000,3145728 root=/dev/ram0 rw)
 修改为:
 noinitrd root=/dev/nfs rw nfsroot=192.168.1.108:/nfsboot/rootfs ip=192.168.1.118:192.168.1.108::255.255.255.0 console=ttyS0,115200 init=/linuxrc mem=64M
 
 选择如下配置:
 System Type  --->
 Atmel AT91 System-on-Chip  --->
 [*]   9G9260-EK Evaluation Kit   
 保存配置:
 root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260# cp .config 9g9260ek_defconfig
 root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260# mv 9g9260ek_defconfig arch/arm/configs/

6,编译发布:
root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260# make 9g9260ek_defconfig
root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260# make uImage
root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260# cp arch/arm/boot/uImage uImage-2.6.27-9g9260.bin
root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260# sz uImage-2.6.27-9g9260.bin
7,清除配置
root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260# make distclean
root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260# make mrproper

#29 VMWare/Linux/Ubuntu/Fedora/CentOS/U-BOOT » 测试基于linux-2.6.27的9G9260开发板I2C驱动--缥缈九哥 » 2020-05-09 20:56:36

缥缈九哥
回复: 0

测试基于linux-2.6.27的9G9260开发板I2C驱动
 
1,找到drivers/i2c/busses/i2c-at91.c文件
root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260#  vi drivers/i2c/busses/Makefile
在第28行看到:

obj-$(CONFIG_I2C_AT91)  += i2c-at91.o

2, 找到drivers/i2c/busses/Kconfig文件
root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260#  vi drivers/i2c/busses/Kconfig
在第259行看到:

 config I2C_AT91
  tristate "Atmel AT91 I2C Two-Wire interface (TWI)"
  depends on ARCH_AT91 && EXPERIMENTAL && BROKEN
  help
    This supports the use of the I2C interface on Atmel AT91
    processors.
 
    This driver is BROKEN because the controller which it uses
    will easily trigger RX overrun and TX underrun errors.  Using
    low I2C clock rates may partially work around those issues
    on some systems.  Another serious problem is that there is no
    documented way to issue repeated START conditions, as needed
    to support combined I2C messages.  Use the i2c-gpio driver
    unless your system can cope with those limitations.
 

 
说明AT91 I2C标准驱动不稳定,需要用GPIO模拟!!!

3,编译配置内核
root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260#  make menuconfig
进入配置菜单添加驱动到内核:

 Device Drivers  --->   
 <*> I2C support  --->  
 <*>   I2C device interface
    
       I2C Hardware Bus support  --->  
   <*> GPIO-based bitbanging I2C

4, 编译内核生成驱动
root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260#  make

5, 查看内核启动信息
i2c /dev entries driver
i2c-gpio i2c-gpio: using pins 55 (SDA) and 56 (SCL)
6,查看内核系统信息
# cat /proc/devices
会看到
Character devices:
...
  89 i2c
...

# cat /sys/devices/platform/i2c-gpio/i2c-adapter\:i2c-0/name
i2c-gpio-1
7,建立设备结点
mknod /dev/i2c-0 c 89 0
8,编译测试代码
root@yuanxh-desktop:/home/yuanxh/sam9260/i2ctest-1.0-9g9260# arm-linux-gcc -o i2ctest i2ctest.c
root@yuanxh-desktop:/home/yuanxh/sam9260/i2ctest-1.0-9g9260# cp i2ctest /nfsboot/rootfs/app
9,运行测试代码
# /app/i2ctest
I2C Test version 1.0-9g9260 (yuanxihua@21cn.com) Buile on Jan  5 2009 00:54:45
buf[0x00] = 0x46
...

附件:

//i2ctest.c

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>

#define CHIP_ADDR 0x50   //24C64
#define PAGE_SIZE 32
#define I2C_DEV  "/dev/i2c-0"

static int read_eeprom(int fd,char buff[],int addr,int count)
{
 int res;

 if (write(fd,&addr,1)!=1)
 {
  printf("Can't write %s's addr %d\n",I2C_DEV,addr);
  return -1;
 }
 res = read(fd,buff,count);
 printf("read %d bytes at 0x%02x\n\r",res,addr);
 return res;
}
static int write_eeprom(int fd,char buff[],int addr,int count)
{
 int res;
 int i;
 static char sendbuffer[PAGE_SIZE+1];

 memcpy(sendbuffer+1,buff,count);
 sendbuffer[0]=addr;
 
 res = write(fd,&addr,count+1);
 printf("write %d bytes at 0x%02x\n\r",res,addr);
 return res;
}

int main(void)
{
 int fd,i,res;
 unsigned char buf[PAGE_SIZE];
 
 printf("I2C Test version 1.0-9g9260 (yuanxihua@21cn.com) Buile on %s %s\n\r",__DATE__,__TIME__);
 
 fd=open(I2C_DEV,O_RDWR);
 if(fd<0)
 {
  printf("Can't Open %s !!!\n\r",I2C_DEV);
  return -1;
 }
 
 res = ioctl(fd,I2C_TENBIT,0);
 res = ioctl(fd,I2C_SLAVE,CHIP_ADDR);
 
 for(i=0;i<sizeof(buf);i++)
 {
//  write_eeprom(fd,buf,i,1);
 } 
 for(i=0;i<sizeof(buf);i++)
 {
  read_eeprom (fd,buf+i,i,1);
  printf("buf[0x%02x] = 0x%02x\n\r",i,buf[i]);
 }

 close(fd);
 return 0;
}

#30 VMWare/Linux/Ubuntu/Fedora/CentOS/U-BOOT » 移植mtd-utils-20080508到9G9260开发板--缥缈九哥 » 2020-05-09 20:54:46

缥缈九哥
回复: 0

移植mtd-utils-20080508到9G9260开发板

1,下载解压源码:
root@yuanxh-desktop:/home/yuanxh/sam9260# wget http://debian.mirror.inra.fr/debian/pool/main/m/mtd-utils/mtd-utils_20080508.orig.tar.gz
root@yuanxh-desktop:/home/yuanxh/sam9260# wget http://www.zlib.net/zlib-1.2.3.tar.gz
root@yuanxh-desktop:/home/yuanxh/sam9260# wget http://www.oberhumer.com/opensource/lzo/download/lzo-2.03.tar.gz
root@yuanxh-desktop:/home/yuanxh/sam9260# tar xzvf zlib-1.2.3.tar.gz
root@yuanxh-desktop:/home/yuanxh/sam9260# mv zlib-1.2.3 zlib-1.2.3-9g9260
root@yuanxh-desktop:/home/yuanxh/sam9260# tar xzvf lzo-2.03.tar.gz
root@yuanxh-desktop:/home/yuanxh/sam9260# mv lzo-2.03 lzo-2.03-9g9260
root@yuanxh-desktop:/home/yuanxh/sam9260# tar xzvf mtd-utils_20080508.orig.tar.gz
root@yuanxh-desktop:/home/yuanxh/sam9260# mv mtd-utils-20080508 mtd-utils-20080508-9g9260

2,编译安装zlib:
root@yuanxh-desktop:/home/yuanxh/sam9260# cd zlib-1.2.3-9g9260
root@yuanxh-desktop:/home/yuanxh/sam9260/zlib-1.2.3-9g9260# CC=arm-linux-gcc ./configure --shared --prefix=/usr/zlib-1.2.3   
root@yuanxh-desktop:/home/yuanxh/sam9260/zlib-1.2.3-9g9260# make
root@yuanxh-desktop:/home/yuanxh/sam9260/zlib-1.2.3-9g9260# make install
root@yuanxh-desktop:/home/yuanxh/sam9260/zlib-1.2.3-9g9260# cd ..

3,编译安装lzo:
root@yuanxh-desktop:/home/yuanxh/sam9260# cd lzo-2.03-9g9260/
root@yuanxh-desktop:/home/yuanxh/sam9260/lzo-2.03-9g9260# CC=arm-linux-gcc ./configure --host=arm-linux --prefix=/usr/lzo-2.03
root@yuanxh-desktop:/home/yuanxh/sam9260/lzo-2.03-9g9260# make
root@yuanxh-desktop:/home/yuanxh/sam9260/lzo-2.03-9g9260# make install
root@yuanxh-desktop:/home/yuanxh/sam9260/lzo-2.03-9g9260# cd ..

4,修改mtd-utils的Makefile文件
root@yuanxh-desktop:/home/yuanxh/sam9260# cd mtd-utils-20080508-9g9260/
root@yuanxh-desktop:/home/yuanxh/sam9260/mtd-utils-20080508-9g9260# cp Makefile Makefile.arm
root@yuanxh-desktop:/home/yuanxh/sam9260/mtd-utils-20080508-9g9260# cp Makefile Makefile.x86

修改Makefile.arm文件
root@yuanxh-desktop:/home/yuanxh/sam9260/mtd-utils-20080508-9g9260# vi Makefile.arm
把第8行的 #CROSS=arm-linux-
修改为  CROSS=arm-linux-

把第10行的  CFLAGS := -I./include $(OPTFLAGS)
修改为
    CFLAGS := -I./include $(OPTFLAGS) -I/usr/zlib-1.2.3/include -I/usr/lzo-2.03/include
    LDFLAGS := -L/usr/zlib-1.2.3/lib -L/usr/lzo-2.03/lib
把第46行的  make -C $(BUILDDIR)/ubi-utils
修改为   make -C ubi-utils

把第46行的  make -C $(BUILDDIR)/ubi-utils clean
修改为   make -C ubi-utils clean

5,增加mtd-utils的编译脚本   
root@yuanxh-desktop:/home/yuanxh/sam9260/mtd-utils-20080508-9g9260# vi mkall
在 mkall中写入:
  make -f Makefile.$1  clean
  make -f Makefile.$1  WITHOUT_XATTR=1
root@yuanxh-desktop:/home/yuanxh/sam9260/mtd-utils-20080508-9g9260# vi mkclean
在 mkall中写入:
  make -f Makefile.$1  clean
保存后修改可执行权限
root@yuanxh-desktop:/home/yuanxh/sam9260/mtd-utils-20080508-9g9260# chmod 777 mkall
root@yuanxh-desktop:/home/yuanxh/sam9260/mtd-utils-20080508-9g9260# chmod 777 mkclean

6,编译mtd-utils
ARM版本   
root@yuanxh-desktop:/home/yuanxh/sam9260/mtd-utils-20080508-9g9260# ./mkall arm
可以得到flash_eraseall等工具命令
X86版本
root@yuanxh-desktop:/home/yuanxh/sam9260/mtd-utils-20080508-9g9260# ./mkall x86
可以得到mkfs.jffs2等工具命令

7,清除mtd-utils目标码
root@yuanxh-desktop:/home/yuanxh/sam9260/mtd-utils-20080508-9g9260# ./mkclean arm
root@yuanxh-desktop:/home/yuanxh/sam9260/mtd-utils-20080508-9g9260# ./mkclean x86

#31 VMWare/Linux/Ubuntu/Fedora/CentOS/U-BOOT » 测试基于linux-2.6.27的9G9260开发板MTD驱动 --缥缈九哥 » 2020-05-09 20:53:36

缥缈九哥
回复: 0

测试基于linux-2.6.27的9G9260开发板MTD驱动

1,修改内核源码:
root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260# vi arch/arm/mach-at91/board-sam9260ek.c
在第174行修改成如下:

 /*
  * NAND flash
  */
 static struct mtd_partition __initdata ek_nand_partition[] = {
  {
   .name   = "Bootstrap",
   .offset = 0,
   .size   = 0x20000,
  },
  {
   .name   = "U-boot",
   .offset = 0x20000,
   .size   = 0xe0000,
  },
  {
   .name   = "uImage",
   .offset = 0x100000,
   .size   = 0x200000,
  },
  {
   .name   = "ramdisk",
   .offset = 0x300000,
   .size   = 0x400000,
  },
  {
   .name   = "rootfs",
   .offset = 0x700000,
   .size   = 0x900000,
  },
  {
   .name   = "data",
   .offset = 16 * 1024 * 1024,
   .size   = MTDPART_SIZ_FULL,
  },
 };

2,修改内核配置:

 root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260# make menuconfig

    Boot options  ---> 
  (mem=64M console=ttyS0,115200 root=/dev/mtdblock4 rootfstype=jffs2 init=/linuxrc)
  
 Device Drivers  --->
 <*> Memory Technology Device (MTD) support  --->
 <*>   MTD concatenating support
 [*]   MTD partitioning support
 [*]     Command line partition table parsing
 <*>   Direct char device access to MTD devices
 -*-   Common interface to block layer for MTD 'translation layers'
 <*>   Caching block device access to MTD devices 
 <*>   NAND Device Support  --->
 <*>   Support for NAND Flash / SmartMedia on AT91 and AVR32
         ECC management for NAND Flash / SmartMedia on AT91 / AVR32 (Software ECC)  --->

 File systems  --->
 <*> Second extended fs support
 Miscellaneous filesystems  --->
 <*> Journalling Flash File System v2 (JFFS2) support 
 (0)   JFFS2 debugging verbosity (0 = quiet, 2 = noisy) 
 [*]   JFFS2 write-buffering support
 [*]   JFFS2 summary support (EXPERIMENTAL)

默认就是如此,不作修改。

3,编译内核:
root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260# make uImage
root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260# cp arch/arm/boot/uImage uImage-2.6.27-9g9260.bin
root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260# sz  uImage-2.6.27-9g9260.bin

4,生成JFFS2文件系统:
root@yuanxh-desktop:/nfsboot# ./mkfs.jffs2 -d rootfs -o jffs2-2.6.27-9g9260.bin -n --pagesize=0x800 --eraseblock=0x20000 --pad=0x900000
root@yuanxh-desktop:/nfsboot# sz jffs2-2.6.27-9g9260.bin

5,测试MTD驱动
# cat /proc/mtd
# flash_eraseall /dev/mtd5
# mount -t jffs2 /dev/mtdblock5 /mnt
# cd /app
# touch yuanxihua
# vi yuanxhua
掉电后重新启动,看到文件及内容还存在。

#32 VMWare/Linux/Ubuntu/Fedora/CentOS/U-BOOT » 添加AL9V576的CHAR驱动到基于linux-2.6.27的9G9260开发板--缥缈九哥 » 2020-05-09 20:51:46

缥缈九哥
回复: 0

添加AL9V576的CHAR驱动到基于linux-2.6.27的9G9260开发板
 
1,修改drivers/char/Makefile文件
root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260#  vi drivers/char/Makefile
在第102行添加:

obj-$(CONFIG_FY_AL9V576) += al9v576.o

2, 修改drivers/char/Kconfig文件
root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260#  vi drivers/char/Kconfig
在第1123行添加:

config FY_AL9V576
  tristate "AverLogic AL9V576 MPEG-4/2/1 A/V Encoder"
  depends on MACH_9G9260EK
  help
    If you say yes here you get support for the
    AverLogic AL9V576 MPEG-4/2/1 A/V Encoder.

    This driver can also be built as a module. If so, the module
    will be called al9v576.
config FY_AL9V576_DEBUG
  boolean "AL9V576 Encoder debug messages"
  depends on MACH_9G9260EK && FY_AL9V576
  help
    Select this if you want AL9V576 debug messages
 
3,编译配置内核
root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260#  make menuconfig
进入配置菜单添加驱动到内核:

    System Type  --->  
 Atmel AT91 System-on-Chip  --->
 [*] Atmel AT91SAM9260-EK / AT91SAM9XE Evaluation Kit  
 [*]   9G9260-EK Evaluation Kit 
 
    Device Drivers  ---> 
 Character devices  --->
 <M> AverLogic AL9V576 MPEG-4/2/1 A/V Encoder 
 [*]   AL9V576 Encoder debug messages

     
4,修改arch/arm/mach-at91/board-sam9260ek.c文件
root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260#  vi arch/arm/mach-at91/board-sam9260ek.c
在头文件列表后添加:

  #include <mach/at91sam9260.h>
  #include <mach/at91sam9260_matrix.h>
  #include <mach/at91sam9_smc.h>
 
 在static void __init ek_board_init(void)内部添加: 
  #if defined(CONFIG_MACH_9G9260EK)
   /* al9v576 */
   at91_add_device_al9v576();  
  #endif
  
 在static void __init ek_board_init(void)前面添加:
  #if defined(CONFIG_MACH_9G9260EK)

  #define AL9V576_BASE AT91_CHIPSELECT_0
  #define AL9V576_SIZE SZ_1K
  
  static struct resource al9v576_resources[] =
  {
   {
    .start = AL9V576_BASE,
    .end = AL9V576_BASE + AL9V576_SIZE - 1,
    .flags = IORESOURCE_MEM,
   }
  };
  
  static struct platform_device al9v576_driver =
  {
   .name  = "al9v576",
   .id   = 0,
   .dev  =
   {
    .platform_data = NULL,
   },
   .resource = al9v576_resources,
   .num_resources = ARRAY_SIZE(al9v576_resources),
  };
  
  static struct sam9_smc_config __initdata al9v576_smc_config =
  {
   .ncs_read_setup  = 0x01,
   .nrd_setup   = 0x02,
   .ncs_write_setup = 0x01,
   .nwe_setup   = 0x02,
  
   .ncs_read_pulse  = 0x08,
   .nrd_pulse   = 0x06,
   .ncs_write_pulse = 0x08,
   .nwe_pulse   = 0x06,
  
   .read_cycle   = 0x12,
   .write_cycle  = 0x12,
  
   .mode    = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE,
   .tdf_cycles   = 0x08,
  };
  
  static __init void at91_add_device_al9v576(void)
  {
   unsigned long csa;
  
   csa = at91_sys_read(AT91_MATRIX_EBICSA);
   at91_sys_write(AT91_MATRIX_EBICSA, csa | AT91_MATRIX_VDDIOMSEL_3_3V);
   
   /* setup bus-width (8 or 16) */
  #if defined(CONFIG_AL9V576_BUSWIDTH_16)
    al9v576_smc_config.mode |= AT91_SMC_DBW_16;
  #else
    al9v576_smc_config.mode |= AT91_SMC_DBW_8;
  #endif
   /* configure chip-select 0 (AL9V576) */
   sam9_smc_configure(0, &al9v576_smc_config);
  
   platform_device_register(&al9v576_driver);
  }
  #endif

5,添加drivers/char/al9v576.h文件
root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260#  vi drivers/char/al9v576.h
添加的源码见附件。
6,添加drivers/char/al9v576.c文件
root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260#  vi drivers/char/al9v576.c
添加的源码见附件。
7, 编译内核生成驱动
root@yuanxh-desktop:/home/yuanxh/sam9260/linux-2.6.27-9g9260#  make

附件:

(保密)

#33 Cortex M0/M3/M4/M7 » 9G-STM32 EWARM开发过程简介--缥缈九哥 » 2020-05-09 20:47:00

缥缈九哥
回复: 0

9G-STM32 EWARM开发过程简介

一,准备EWARM+JLINK+STM32软件包

1,在http://www.mcu123.com/down/view.asp?id=83
    下载IAR Embedded Workbench for ARM v5.20版本
    EWARM-EV-WEB-520.rar
    http://esoft.mcu123.com/MCU123_temp_0080309@/arm/EWARM-EV-WEB-520.rar
    (注册机自行查找,安装过程略)
2,在http://www.segger.com/download_jlink.html
    下载Software and documentation pack V4.04a软件
Setup_JLinkARM_V404a.zip
http://www.segger.com/pub/jlink/Setup_JLinkARM_V404a.zip
    (JLINK自行购买,安装过程略)
3,在http://www.st.com/mcu/devicedocs-STM32F103T8-110.html
    下载ARM-based 32-bit MCU STM32F10xxx standard peripheral library
    stm32f10x_stdperiph_lib_v3.0.0.zip
http://www.st.com/stonline/products/support/micro/files/stm32f10x_stdperiph_lib_v3.0.0.zip
       
二,建立STM32 LCCD工程

1,解压stm32f10x_stdperiph_lib_v3.0.0.zip软件包,把其中的“Libraries”和“Project”文件夹复制到“D:\works\lccd-1.0.0\”,
在“D:\works\lccd-1.0.0\”下建立“Drivers”、“Linker”、“Include”和“Source”空文件夹,在“D:\works\lccd-1.0.0\Project”
下建立“Stm32f103”空文件夹,把“Project\Template”下的C文件复制到“Source”和H文件复制到“Include”,把“Project\Template\
EWARMv5”下的所有ICF文件复制到“Linker”;
2,在EWARM菜单中“Project”->“Create New Project”打开“Create New Project”窗口,点击“OK”打开“另存为”窗口,
选择项目工程存储路径“D:\works\lccd-1.0.0\Project\Stm32f103\”填写项目文件名“lccd.ewp",在菜单中“File”->“Save All”
打开“Save Workspace As”窗口,填写工作环境文件名“lccd.eww”;
3,在EWARM的左面“Workspace”窗口下面的“Files”空白部分右击鼠标,选择“Add”->“Add Group”出现““Add Group - lccd”窗口,
在“Group name”中填上“CMSIS”,同样方法建立“USER”“BOOT”“DRV”“INC”“LIB”等文件组后点击“Save All”快捷键;
4,在EWARM的左面“Workspace”窗口下面的“CMSIS”上右击鼠标,选择“Add”->“Add Files”出现““Add Files - CMSIS”窗口,选择
打开“D:\works\lccd-1.0.0\Libraries\CMSIS\Core\CM3”文件夹下的“core_cm3.c”和“system_stm32f10x.c”文件;
5,在EWARM的左面“Workspace”窗口下面的“BOOT”上右击鼠标,选择“Add”->“Add Files”出现““Add Files - BOOT”窗口,选择
打开“D:\works\lccd-1.0.0\Libraries\CMSIS\Core\CM3\startup\iar”文件夹下的“startup_stm32f10x_md.s”文件;
6,在EWARM的左面“Workspace”窗口下面的“LIB”上右击鼠标,选择“Add”->“Add Files”出现““Add Files - LIB”窗口,选择
打开“D:\works\lccd-1.0.0\Libraries\STM32F10x_StdPeriph_Driver\src”文件夹下的“stm32f10x_gpio.c”等所有C文件;
7,在EWARM的左面“Workspace”窗口下面的“INC”上右击鼠标,选择“Add”->“Add Files”出现““Add Files - INC”窗口,选择
打开“D:\works\lccd-1.0.0\Include”文件夹下的所有H文件;
8,在EWARM的左面“Workspace”窗口下面的“USER”上右击鼠标,选择“Add”->“Add Files”出现““Add Files - USER ”窗口,选择
打开“D:\works\lccd-1.0.0\Source”文件夹下的所有C文件,点击“Save All”快捷键;

三,配置STM32 LCCD工程

在EWARM的左面“Workspace”窗口下面的“Files”的“lccd - Debug”左击鼠标,选择“Project”->“Options”出现“Options for node "lccd"”窗口;

1,在左面“Category:”中选择上“General Options”,在“Target”->“Processor Variant”->“Device”中选择“ST STM32F10xx8”,
在“Library Configuration”->“Library”中选择“FULL”;
2,在左面“Category:”中选择上“C/C++ Complier”,在“Preprocessor”->“Additional include directories:”中填上下面几行:
  $PROJ_DIR$\..\..\Include
  $PROJ_DIR$\..\..\Libraries\CMSIS\Core\CM3
  $PROJ_DIR$\..\..\Libraries\STM32F10x_StdPeriph_Driver\inc
在“Preprocessor”->“Define symbols:”中填上下面几行:
  USE_STDPERIPH_DRIVER
  STM32F10X_MD
  USE_STM3210B_EVAL(我暂时不用)

3,在左面“Category:”中选择上“Output Converter”,在“Output”中勾选“Generate addition output”并在“Output format:”中选择“binary”,
在“Output”->“Output file”中勾选“override default”并填写上目标码文件名:lccd-debug-1.0.0.bin;

4,在左面“Category:”中选择上“Linker”,在“Config”->“Linker configuration file”中勾选“override default”,在下面填上:
  “$PROJ_DIR$\..\..\Linker\stm32f10x_flash.icf”,在“List”中勾选“Generate linker map file”;

5,在左面“Category:”中选择上“Debugger”,在“Setup”->“Driver”中选择“J-link/J-trace”,在“Download”勾选择“Use flash loader”;

6,在左面“Category:”中选择上“J-link/J-trace”,在“Setup”->“JTAG/SWD speed”中选择“Fixed”并填上“4000”,在“Connection”->“Interface”
中选择“SWD”,点击“Save All”快捷键;

7,在EWARM的左面“Workspace”窗口下选择“Release”,然后可以对“lccd - Release”左击鼠标,选择“Project”->“Options”出现“Options for
node "lccd"”窗口,做类似上面“lccd - Debug”的配置,注意不选择调试信息及目标友文件名为lccd-release-1.0.0.bin;

四,调试STM32 LCCD工程

1,在EWARM菜单中“Project”->“Make”打开编译工程命令;
2,在EWARM菜单中“Project”->“Download and Debug”打开下载调试命令;
3,在EWARM菜单中“Debug”->“Go”打开全速运行命令;
4,其它调试命令请自行尝试;

五,修改STM32 LCCD工程

1,移植USART的PRINTF应用
A,把D:\works\lccd-1.0.0\Include\stm32f10x_conf.h的第46行的注释打开;
B,把D:\works\lccd-1.0.0\Project\Examples\USART\Printf\platform_config.h 复制到D:\works\lccd-1.0.0\Include\目录;
C,把D:\works\lccd-1.0.0\Project\Examples\USART\Printf\main.c 复制到D:\works\lccd-1.0.0\Source;
D,编译调试即可以在 RT1看到115200 8N1的字符“USART Printf Example: retarget the C library printf function to the USART”

2,整理USART的PRINTF应用

A,选择Workspace”窗口下的“DRV”用“Project”->“Add Files”把“D:\works\lccd-1.0.0\Drivers\ rt.c”添加到工程;
D:\works\lccd-1.0.0\Drivers\ rt.c的源码如下:

 /* Includes ------------------------------------------------------------------*/
 #include "stm32f10x.h"
 #include "stdio.h"
 #include "platform_config.h"
 
 /** @addtogroup StdPeriph_Examples
   * @{
   */
 
 /** @addtogroup USART_Printf
   * @{
   */
 
 /* Private typedef -----------------------------------------------------------*/
 /* Private define ------------------------------------------------------------*/
 /* Private macro -------------------------------------------------------------*/
 /* Private variables ---------------------------------------------------------*/
 
 /* Private function prototypes -----------------------------------------------*/
 void RT_Configuration(void);
 
 /* Private functions ---------------------------------------------------------*/
 
 
 /**
   * @brief  Configures the different GPIO ports.
   * @param  None
   * @retval : None
   */
 void RT_Configuration(void)
 {
   GPIO_InitTypeDef GPIO_InitStructure;
   USART_InitTypeDef USART_InitStructure;
 
 #if defined USE_USART2 && defined USE_STM3210B_EVAL
   /* Enable AFIO clock */
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
 
   /* Enable the USART2 Pins Software Remapping */
   GPIO_PinRemapConfig(GPIO_Remap_USART2, ENABLE);
 #endif
 
   /* Configure USARTx_Tx as alternate function push-pull */
   GPIO_InitStructure.GPIO_Pin = GPIO_TxPin;
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
   GPIO_Init(GPIOx, &GPIO_InitStructure);
 
   /* Configure USARTx_Rx as input floating */
   GPIO_InitStructure.GPIO_Pin = GPIO_RxPin;
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
   GPIO_Init(GPIOx, &GPIO_InitStructure);
 
   /* USARTx configuration ------------------------------------------------------*/
   /* USARTx configured as follow:
         - BaudRate = 115200 baud 
         - Word Length = 8 Bits
         - One Stop Bit
         - No parity
         - Hardware flow control disabled (RTS and CTS signals)
         - Receive and transmit enabled
   */
   USART_InitStructure.USART_BaudRate = 115200;
   USART_InitStructure.USART_WordLength = USART_WordLength_8b;
   USART_InitStructure.USART_StopBits = USART_StopBits_1;
   USART_InitStructure.USART_Parity = USART_Parity_No ;
   USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
   USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
  
   /* Configure the USARTx */
   USART_Init(USARTx, &USART_InitStructure);
   /* Enable the USARTx */
   USART_Cmd(USARTx, ENABLE);
  
 }
 
 /**
   * @brief  Retargets the C library printf function to the USART.
   * @param  None
   * @retval : None
   */
 int fputc(int ch, FILE *f)
 {
   /* Write a character to the USART */
   USART_SendData(USARTx, (uint8_t) ch);
 
   /* Loop until the end of transmission */
   while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET)
   {
   }
 
   return ch;
 }
 /*******************************************************************************
 * Function Name  : fgetc
 * Description    : Get a key from the HyperTerminal
 * Input          : None
 * Output         : None
 * Return         : The Key Pressed
 *******************************************************************************/
 int fgetc(FILE *f)
 {
  /* Waiting for user input */
  while ( USART_GetFlagStatus(USARTx, USART_FLAG_RXNE) == RESET);
  return (uint8_t)USARTx->DR;
 }
B,修改D:\works\lccd-1.0.0\Source\main.c的int main(void)如下:
 int main(void)
 {
   /* System Clocks Configuration */
   RCC_Configuration();
 
   /* Configure the GPIO ports */
   RT_Configuration();
 
   /* Output a message on Hyperterminal using printf function */
   printf("\n\r\n\r\n\r\n\r");
   printf("*** LCCD V1.0 Build by y nxih @21cn.com on ("__DATE__ " - " __TIME__ ")\n\r");
   printf("*** LCCD V1.0 Rebooting ...\n\r");
 
   while (1)
   {
   }
 }

并在文件前添加:
extern void RT_Configuration(void);

#34 Cortex M0/M3/M4/M7 » 9G-STM32 EWARM开发过程简介之二--缥缈九哥 » 2020-05-09 20:46:18

缥缈九哥
回复: 0

9G-STM32 EWARM开发过程简介之二

六,移植STM32 LCCD工程

1,移植GPIO的IOToggle应用

A,选择Workspace”窗口下的“DRV”用“Project”->“Add Files”把“D:\works\lccd-1.0.0\Drivers\gpio.c”添加到工程;
D:\works\lccd-1.0.0\Drivers\gpio.c的源码如下:
(参考GPIO/IOToggle/main.c)
B,修改D:\works\lccd-1.0.0\Source\main.c的int main(void) 的while (1)前加上:
   /* Configure the GPIO ports */
   GPIO_Configuration();
while (1)里面加上:
   {
     printf("*** LCCD V1.0 running %d \n\r",i++);
     GPIO_Test();
   }
并在文件前添加:
extern void GPIO_Configuration(void);
extern void GPIO_Test(void);

2,移植SYSTICK的应用

A,在D:\works\lccd-1.0.0\Source\main.c的int main(void)添加:
  /* Setup SysTick Timer for 1 msec interrupts  */
   if (SysTick_Config(SystemFrequency / 1000))
   {
     /* Capture error */
     while (1);
   }
B,在D:\works\lccd-1.0.0\Source\stm32f10x_it.c 的 void SysTick_Handler(void) 加上:
   TimingDelay_Decrement();  文件前加上:
extern void TimingDelay_Decrement(void);

C,选择Workspace”窗口下的“DRV”用“Project”->“Add Files”把“D:\works\lccd-1.0.0\Drivers\time.c”添加到工程;
D:\works\lccd-1.0.0\Drivers\time.c的源码如下:
(参考SysTick/main.c)

3,移植DMA的ADC1的应用

A,修改D:\works\lccd-1.0.0\Source\main.c的int main(void) 的while (1)前加上:
     /* ADC1 Configuration */
    ADC_Configuration();
while (1)里面加上:
     printf("*** LCCD V1.0 running %d adc =%d mv \n\r",i++,(unsigned int)ADC_read());
并在文件前添加:
extern void ADC_Configuration(void);
extern unsigned int ADC_read(void);

B,在D:\works\lccd-1.0.0\Source\stm32f10x_it.c 的 void SysTick_Handler(void) 加上:
    ADC_filter();
   文件前加上:
extern unsigned int ADC_filter(void);

C,在D:\works\lccd-1.0.0\Include\stm32f10x_conf.h 中,打开注释:
#include "stm32f10x_adc.h"
#include "stm32f10x_dma.h"

D,选择Workspace”窗口下的“DRV”用“Project”->“Add Files”把“D:\works\lccd-1.0.0\Drivers\adc.c”添加到工程;
D:\works\lccd-1.0.0\Drivers\adc.c的源码如下:
(参考ADC/ADC1_DMA/main.c)

4,移植TIM的PWM应用

A,修改D:\works\lccd-1.0.0\Source\main.c的int main(void) 的while (1)前加上:
     /* TIM1 Configuration */
    TIM2_Configuration();
     /* TIM1 Configuration */
    TIM2_Configuration();
并在文件前添加:
extern void TIM1_Configuration(void);
extern void TIM2_Configuration(void);


B,选择Workspace”窗口下的“DRV”用“Project”->“Add Files”把“D:\works\lccd-1.0.0\Drivers\tim.c”添加到工程;
D:\works\lccd-1.0.0\Drivers\tim.c的源码如下:
(参考TIM/PWM_Output/main.c)

5,移植EXTI的外部中断应用

A,修改D:\works\lccd-1.0.0\Source\main.c的int main(void) 的while (1)前加上:
     /* EXTI Configuration */
  EXTI_Configuration();
并在文件前添加:
  extern void EXTI_Configuration(void);

B,在D:\works\lccd-1.0.0\Source\stm32f10x_it.c 的 void SysTick_Handler(void) 后面加上:
void EXTI0_IRQHandler(void)
{
    if(EXTI_GetITStatus(EXTI_Line0) != RESET)
    {
   EXTI_PA0_IRQHandler();
   /* Clear the EXTI_Line9 pending bit */
      EXTI_ClearITPendingBit(EXTI_Line0);
  }
}
在文件前加上:
extern void EXTI_PA0_IRQHandler(void);

C, 在D:\works\lccd-1.0.0\Include\stm32f10x_it.h 的 void SysTick_Handler(void) 后面加上
void EXTI0_IRQHandler(void);

D,在D:\works\lccd-1.0.0\Include\stm32f10x_conf.h 中,打开注释:
#include "stm32f10x_exti.h"
#include "misc.h"

E,选择Workspace”窗口下的“DRV”用“Project”->“Add Files”把“D:\works\lccd-1.0.0\Drivers\exti.c”添加到工程;
D:\works\lccd-1.0.0\Drivers\exti.c的源码如下:
(NVIC/Priority/main.c)

#35 ST/STM8/STM8S/STM8L » 9G-AVR EWAVR开发过程简介--缥缈九哥 » 2020-05-09 20:45:26

缥缈九哥
回复: 2

9G-AVR EWAVR开发过程简介

一,准备EWARM+AVR STUDIO+PROTEUS+UIP软件包

1,在http://www.mcu123.com/news/Soft/embsof/avr/200902/491.html
    下载IAR Embedded Workbench for AVR 5.20 FULL版本
    CD-EWAVR-520-2.zip
    http://esoft.mcu123.com/MCU123_temp_0080309@/avr/CD-EWAVR-520-2.zip
    (注册机自行查找,安装过程略)
2,在http://www.atmel.com/dyn/products/tools_card.asp?tool_id=2725
    下载AVR Studio 4.16 (build 628)软件
AvrStudio416Setup.exe
http://www.atmel.com/dyn/resources/prod_documents/AvrStudio416Setup.exe
    (AVRISP自行购买,安装过程略)
3, 在http://bbs.cechina.cn/ShowTopic.aspx?id=78131上下载
Proteus Pro 7[1].4 sp3.part01.rar 到 Proteus Pro 7[1].4 sp3.part15.rar
其中Proteus Pro 7[1].4 sp3.part08.rar下载不了,请到
在http://bbs.eeworld.com.cn/viewthread.php?tid=71645上注册下载
    下载Proteus Pro 7.4 sp3.part08.rar (3.91 MB) 软件
Proteus_Pro_7.4_sp3.part08.rar
按次序改名成Proteus_Pro_7.4_sp3.part01.rar至Proteus_Pro_7.4_sp3.part15.rar后
解压即得到Proteus Pro 7.4 sp3软件及基注册号和破解补丁;
(汉化文件自己找)
4,在http://www.sics.se/~adam/uip/index.php/Download
    下载uip-1.0.tar.gz软件
uip-1.0.tar.gz
http://www.sics.se/~adam/download/?f=uip-1.0.tar.gz
5,在http://www.tuxgraphics.org/common/src2/article09051/上下载
eth_tcp_client_server-3.3.tar.gz
http://www.tuxgraphics.org/common/src2/article09051/eth_tcp_client_server-3.3.tar.gz
       
二,建立AVR NET工程

1,在IAR EW IDE菜单中“Project”->“Create New Project”打开“Create New Project”窗口,点击“OK”打开“另存为”窗口,
选择项目工程存储路径“D:\works\avrnet-1.0.0\Project\”填写项目文件名“avrnet.ewp",在菜单中“File”->“Save All”
打开“Save Workspace As”窗口,填写工作环境文件名“avrnet.eww”;
2,在“D:\works\avrnet-1.0.0\”下建立“driver”、“atmega32”“include”和“source”空文件夹;

3,在D:\works\avrnet-1.0.0\driver\下建立uart.c如下:
#include "config.h"

void uart0_init(void)
{
  UCSRB = 0x00; //disable while setting baud rate
  UCSRA = 0x00;
  UCSRC = (1<<URSEL) | 0x06;
  UBRRL = 0x33; //set baud rate lo
  UBRRH = 0x00; //set baud rate hi
  UCSRB = 0x18;
}

int putchar(int c)
{
  while(!(UCSRA&(1<<UDRE)));
  UDR=(char)c;
  return 0;
}
int getchar(void)
{
  while(!(UCSRA&(1<<RXC)));
  return (int)UDR;
}

4,在D:\works\avrnet-1.0.0\atmega32\下建立main.c如下:
#include "config.h"

extern void uart0_init(void);
void init_devices(void)
{
  _CLI(); //disable all interrupts
  MCUCR = 0x00;
  MCUCSR = 0x80;//禁止JTAG
  GICR   = 0x00;
  uart0_init();
  _SEI(); //re-enable interrupts
}
int main(void)
{
  unsigned int i=0;
     init_devices();
     printf("\n\r\n\r\n\rAVRnet Version 1.0-ATmega32A (yuanxihuah@21cn.com) Build on %s %s\n\r\n\r",__DATE__,__TIME__);
  while(1)
  {
         __delay_cycles(16*1000);
       
         printf("\n\rAVRnet-1.0.0 run time = %d ...",i++);
  }
}

5,在D:\works\avrnet-1.0.0\include\下建立config.h如下:
#include <stdio.h>
#ifndef ENABLE_BIT_DEFINITIONS
#define ENABLE_BIT_DEFINITIONS
// Enable the bit definitions in the iom128.h file
#endif

#include <avr_macros.h>
#include <ina90.h>
#include <intrinsics.h>
#include <iomacro.h>
#include <iom32a.h>

三,配置AVR NET工程

1, 在IAR EW IDE的左面“Workspace”窗口下面的“Files”空白部分右击鼠标,选择“Add”->“Add Group”出现““Add Group - avrnet”窗口,
在“Group name”中填上“DRV”,同样方法建立“SRC”“INC”“LIB”等文件组后点击“Save All”快捷键;
2, 在IAR EW IDE的左面“Workspace”窗口下面的“SRC”上右击鼠标,选择“Add”->“Add Files”出现““Add Files - SRC”窗口,选择
打开“D:\works\avrnet-1.0.0\atmega32”文件夹下的main.c文件;
3, 在IAR EW IDE的左面“Workspace”窗口下面的“SRC”上右击鼠标,选择“Add”->“Add Files”出现““Add Files - SRC”窗口,选择
打开“D:\works\avrnet-1.0.0\driver”文件夹下的uart.c文件;
 
在IAR EW IDE的左面“Workspace”窗口下面的“Files”的“avrnet - Release”左击鼠标,选择“Project”->“Options”出现“Options for node "avrnet"”窗口;
4,在左面“Category:”中选择上“General Options”,在“Target”->“Processor configuration”中选择“--cpu=m32a,  Atmega32A”,
“Memory model”中选择“Small”;
5,在左面“Category:”中选择上“C/C++ Complier”,在“Preprocessor”->“Additional include directories:”中填上下面几行:
$PROJ_DIR$\..\include
$PROJ_DIR$\..\library\uip-1.0\uip
6,在左面“Category:”中选择上“Linker”,在“Output”中勾选“override default”,在下面填上:avrnet-1.0.0.hex
在“Format”中勾选“Other”并在“Output”后面选择上“intel-standard”;

四,调试AVR NET工程

1,在IAR EW IDE菜单中“Project”->“Make”打开编译工程命令生成目标码:
D:\works\avrnet-1.0.0\project\Release\Exe\avrnet-1.0.0.hex
2,利用Proteus仿真程序(自行实现)。

五,移植AVR NET工程

1,解压uip-1.0.tar.gz软件包,把全部代码的“uip-1.0”文件夹复制到“D:\works\avrnet-1.0.0\library”,修改D:\works\avrnet-1.0.0\library\uip-1.0\unix\main.c
为uip_main.c并与其它C文件一起复制到D:\works\avrnet-1.0.0\atmega32,H文件复制到D:\works\avrnet-1.0.0\include下面;
2,在IAR EW IDE的左面“Workspace”窗口下面的“Files”空白部分右击鼠标,选择“Add”->“Add Group”出现“Add Group - avrnet”窗口,
在“Group name”中填上“UIP”后点击“Save All”快捷键;
3,在IAR EW IDE的左面“Workspace”窗口下面的“UIP”上右击鼠标,选择“Add”->“Add  Group”出现““Add  Group - UIP”窗口,
在“Group name”中填上“UIP”,同样方法建立“APPS”“LIB”“UNIX”等文件组后点击“Save All”快捷键;
4,在IAR EW IDE的左面“Workspace”窗口“UIP”下面的“UIP”上右击鼠标,选择“Add”->“Add Files”出现“Add Files - UIP”窗口,选择
打开“D:\works\avrnet-1.0.0\library\uip-1.0\uip” 文件夹下的8个C文件;
5,在IAR EW IDE的左面“Workspace”窗口“UIP”下面的“LIB”上右击鼠标,选择“Add”->“Add Files”出现“Add Files - LIB”窗口,选择
打开“D:\works\avrnet-1.0.0\library\uip-1.0\lib” 文件夹下的1个C文件;

6,在D:\works\avrnet-1.0.0\include建立inttypes.h文件:

#ifndef __INTTYPES_H_
#define __INTTYPES_H_

typedef signed char int8_t;
typedef unsigned char uint8_t;
typedef signed int int16_t;
typedef unsigned int uint16_t;
typedef signed long int int32_t;
typedef unsigned long int uint32_t;
typedef signed long long int int64_t;
typedef unsigned long long int uint64_t;

#endif /* __INTTYPES_H_ */

7,添加ENC28J60驱动
解压eth_tcp_client_server-3.3.tar.gz文件包,把其中的enc28j60.c和enc28j60.h复制到D:\works\avrnet-1.0.0\driver目录;
用上面类似的方式添加到工程目录“DRV”中;
把enc28j60.c的第15行的#include <avr/io.h>修改为:#include "config.h"
把enc28j60.c的第20行的#include <util/delay.h>修改为:#include  "delay.h" //#include <util/delay.h>

在D:\works\avrnet-1.0.0\include建立delay.h文件,实现以下延时接口;
  void _delay_loop_1(uint8_t __count){}
  void _delay_loop_2(uint16_t __count){}
  void _delay_ms(double __ms){}
  void _delay_us(double __us){}
 
修改D:\works\avrnet-1.0.0\atmega32\tapdev.c文件的驱动接口函数:
  #include "config.h"
  #include "uip.h"
  #include "clock-arch.h"
 
  extern void enc28j60Init(uint8_t* macaddr);
  extern uint16_t enc28j60PacketReceive(uint16_t maxlen, uint8_t* packet);
  extern void enc28j60PacketSend(uint16_t len, uint8_t* packet);
 
  volatile unsigned int Packet_length;
 
  /*---------------------------------------------------------------------------*/
  void tapdev_init(void)
  {
  #if UIP_FIXEDETHADDR == 0
   extern unsigned char avr_mac[];
  #else
   unsigned char avr_mac[] = {UIP_ETHADDR0,UIP_ETHADDR1,UIP_ETHADDR2, UIP_ETHADDR3, UIP_ETHADDR4, UIP_ETHADDR5};
  #endif
   enc28j60Init(avr_mac);
   Packet_length = 0;
   GICR |= 0x01 << 6;
  }
  /*---------------------------------------------------------------------------*/
  unsigned int tapdev_read(void)
  {
   unsigned int temp;
   extern volatile clock_time_t sys_ticks;
   
   temp = sys_ticks;
   while (Packet_length == 0 && temp == sys_ticks) {;}
   
   temp = Packet_length;
   Packet_length = 0;
   return temp;
  }
  /*---------------------------------------------------------------------------*/
  #pragma vector=INT0_vect
  __interrupt void enc28j60_int(void)
  {
   Packet_length = enc28j60PacketReceive(UIP_BUFSIZE,uip_buf);
  }
 
  void tapdev_send(void)
  {
   enc28j60PacketSend(uip_len ,uip_buf);
  }


8,增加系统定时器
把D:\works\avrnet-1.0.0\atmega32的第42行修改为:#include "config.h"//#include <sys/time.h>
在clock_time_t clock_time(void) {}前面增加:volatile clock_time_t sys_ticks;
并且把clock_time_t clock_time(void) {}函数体其它内容注释掉,改为:return sys_ticks;

在D:\works\avrnet-1.0.0\driver建立clock.c文件:
  #include "clock-arch.h"
  #include "config.h"//#include <sys/time.h>
  extern volatile clock_time_t sys_ticks;
 
  void sys_clock_init(void)
  {
   TCCR0 = 0;
   TCCR0 |= (1 << CS02);
   TIMSK |= (1 << TOIE0);
   TCNT0 = 0x06;
   sys_ticks = 0;
  }
 
  #pragma vector=TIMER0_OVF_vect //定时器0溢出中断入口地址
  __interrupt void time0(void)
  {
   TCNT0 = 0x06;
   sys_ticks++; 
  }

六,测试TELNET协议

1, 在IAR EW IDE的左面“Workspace”窗口“UIP”下面的“APPS”上右击鼠标,选择“Add”->“Add Files”出现“Add Files - APPS”窗口,选择
D:\works\avrnet-1.0.0\library\uip-1.0\apps下面的“TELNETD”文件夹的C文件加入到项目后,点击“Save All”快捷键;
2,在左面“Category:”中选择上“C/C++ Complier”,在“Preprocessor”->“Additional include directories:”中填上下面几行:
$PROJ_DIR$\..\library\uip-1.0\apps\telnetd
$PROJ_DIR$\..\library\uip-1.0\lib
3,打开D:\works\avrnet-1.0.0\include\uip-conf.h 把第148行的#include "telnetd.h"注释打开;
4,打开D:\works\avrnet-1.0.0\atmega32\uip_main.c文件,加入#include "config.h" 包含,修改main(void)为uip_main(void),并在其中打开
  telnetd_init();注释掉 /*  httpd_init(); */,完成;
5,在D:\works\avrnet-1.0.0\atmega32\main.c文件前加入extern int uip_main(void);并在while(1) 前加入调用uip_main();主程序,完成。
6,在D:\works\avrnet-1.0.0\include\uip-conf.h中,修改#define UIP_CONF_MAX_CONNECTIONS 6   //40 减少连接数,修改
#define UIP_CONF_MAX_LISTENPORTS 1    //40,修改#define UIP_CONF_BYTE_ORDER      UIP_LITTLE_ENDIAN  //LITTLE_ENDIAN,
并且添加以下代码:
  #define TELNETD_CONF_NUMLINES 1
  #define TELNETD_CONF_LINELEN 40
  #define notdef       0
  #define UIP_CONF_IPV6     0
  #define UIP_ARCH_ADD32     0
  #define UIP_ARCH_CHKSUM     0
  #define UIP_NEIGHBOR_CONF_ADDRTYPE  0
  #define UIP_IPADDR0     192
  #define UIP_IPADDR1     168
  #define UIP_IPADDR2     1
  #define UIP_IPADDR3  80
  #define UIP_NETMASK0    255
  #define UIP_NETMASK1    255
  #define UIP_NETMASK2    255
  #define UIP_NETMASK3    0
  #define UIP_DRIPADDR0   192
  #define UIP_DRIPADDR1   168
  #define UIP_DRIPADDR2   1
  #define UIP_DRIPADDR3   1
  #define UIP_ETHADDR0    'A'
  #define UIP_ETHADDR1    'V'
  #define UIP_ETHADDR2    'R'
  #define UIP_ETHADDR3    'N'
  #define UIP_ETHADDR4    'E'
  #define UIP_ETHADDR5    'T'
 
7,编译通过。(参考了网络上的一些例子,只记得有一个是风城少主的。请多包涵。)

#36 ST/STM8/STM8S/STM8L » 9G-S08 CWS08开发过程简介--缥缈九哥 » 2020-05-09 20:43:55

缥缈九哥
回复: 0

9G-S08 CWS08开发过程简介

一,9G-S08 CWS08开发过程简介

一,准备CWS08+LICEMSE+OSBDM 软件包

1,在http://www.myhcs08.com/upload/soft/CW_MCU_V6_2_SE.rar
    下载CodeWarrior for HCS08 V6.2软件
CW_MCU_V6_2_SE.rar
http://www.myhcs08.com/upload/soft/CW_MCU_V6_2_SE.rar
(自行安装到默认C盘)
   
2,在http://www.ouravr.com/bbs/bbs_content.jsp?bbs_sn=1709998&bbs_page_no=1&bbs_id=2070
    点击此处下载 ourdev_479901.zip(文件大小:3K) (原文件名:licenseForCW62.zip)
    解压后得到文件license.dat
http://www.ouravr.com/bbs/bbs_upload387291/files_11/ourdev_479901.zip
(把license.dat文件解压放在C:\Program Files\Freescale\CodeWarrior for Microcontrollers V6.2目录)

3,在http://shop36265907.taobao.com/
或者http://longqiu.21ic.org 上联系购买
BDM XS128 USBDM V1.3 8/16/32位 通用下载器及驱动程序
如需要自己制作请查看:
http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=1312798&bbs_page_no=1&bbs_id=2070
网址。
         
二,建立工程

1,在XP开始菜单“所有程序->Freescale CodeWarrior->CW for Microcontrollers V6.2”中打开CodeWarrior IDE,
在Startup向导框中选择“Create New Project”向导,点开“HCS08”下面的“HCS08Q Family”选择“MC9S08QD4”按“下一步”;

2,默认选择C语言开发,项目名称用“qd4_ook.mcp”,项目路径用“D:\works\qd4_ook-1.0”点“下一步”,不用添加源码,再点击“下一步”,
快速开发意见选择“None”点击“下一步”,启动代码,内存模式,浮点模式用默认,再点“下一步”,PC-LINT版本管理用“No”,点击“完成”;

3,点开项目工程的“Files”中的“Sources”中的“main.c”,在main.c中的void main(void) { 前添加以下代码:
  void delay_ms(int nms)
  {
   int i,j;
   for(i=0;i<nms;i++)
      { for(j=0;j<300;j++){__RESET_WATCHDOG();}}   //
  }
在  for(;;) { 前添加:
  PTADD = 0xFF;
  PTAD= 0x00;
在  for(;;) { 里添加:
  delay_ms(500);
  PTAD=~PTAD;
 
三,编译工程

1,在IDE左面工程框中选择“HCS08 Open Source BDM”,执行菜单“Project->Make”,编译代码。

四,调试工程

1,插上USB接口的BDM工具及MC9S08QD4的小开发板,(板子由BDM提供5V,GND,RST和BKGD信号,PTA0上上拉一个LED到5V);
2,执行菜单“Project->Debug”,确认弹出两个对话框,就把目标码下载到CPU,并弹出“True-Time Simulator & Real-Time Debugger”工具;
3,在Debugger窗口菜单中执行“Run->Start/Continue”全速运行代码,就能在MC9S08QD4的LED上看到闪烁;
4,其它的高级单步,跳过,跳出,汇编单步,暂停,复位等自行尝试。

#37 ST/STM8/STM8S/STM8L » 9G-S12 CWS12开发过程简介--缥缈九哥 » 2020-05-09 20:41:32

缥缈九哥
回复: 0

9G-S12 CWS12开发过程简介

一,准备CWS12+LICENSE+OSBDM 软件包

1,在http://www.freescale.com/webapp/sps/site/prod_summary.jsp?code=CW-HCS12X&fpsp=1&tab=Design_Tools_Tab
    上注册下载Eval tion: CodeWarrior Development Studio for Freescale HCS12(X) Microcontrollers V5.0 软件
CW_S12_v5.0_Eval.exe
(自行安装到默认C盘)
   
2,在www.mcu123.net/bbs/   上下载uFztvdTV.rar 文件包
    解压后得到文件license.dat
(把license.dat文件解压放在C:\Program Files\Freescale\CodeWarrior for S12(X) V5.0目录)

3,在http://shop36265907.taobao.com/上联系购买
BDM XS128 USBDM V1.3 8/16/32位 通用下载器及驱动程序
如需要自己制作请查看:
http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=1312798&bbs_page_no=1&bbs_id=2070
网址。

           
二,建立9S12_ook工程
1,在启动菜单中打开CodeWarrior IDE,在Startup向导框中选择“Create New Project”向导,点开“HCS12X”下面的“HCS12XS Family”
下面的“MC9S12XS128”器件,点击“下一步”;
2,选择开发语言“C”,项目名称用“ook.mcp”项目路径用“D:\works\9S12_ook-1.0\ook”,再占点击“下一步”;添加源码,再点击“下一步”
初始化代码产生意见用“None”,点击“下一步”;启动代码,内存模式,浮点格式,都用默认,再点击“下一步”;
3,FLASH,RAM的页面影射用默认,点击“下一步”,PC-LINT代码管理意见用“None”,点击“完成”建立项目工程。

三,修改9S12_ook工程
1,打开IDE左面“Files”中“Sources”中的“main.c”文件,把该文件修改如下:
  #include <hidef.h>      /* common defines and macros */
  #include "derivative.h"      /* derivative-specific definitions */
  #include <stdio.h>
 
  extern void SCI_Init(void);
 
  void PLL_init(void)
  {
      CLKSEL=0X00;     // disengage PLL to system
      PLLCTL_PLLON=1;  // turn on PLL
      SYNR=0x00 | 0x01;  // VCOFRQ[7:6];SYNDIV[5:0]
     
      REFDV=0x80 | 0x01;  // REFFRQ[7:6];REFDIV[5:0]
      POSTDIV=0x00;       // 4:0, fPLL= fVCO/(2xPOSTDIV)
     
      _asm(nop);          // BUS CLOCK=16M
      _asm(nop);
      while(!(CRGFLG_LOCK==1));   //when pll is steady ,then use it;
      CLKSEL_PLLSEL =1;         //engage PLL to system;
  }
  void delay_ms(int nms)
  {
   int i,j;
   for(i=0;i<nms;i++)
      { for(j=0;j<2770;j++){;}}   //32MHz--1ms
  }
  void main(void) {
   int i=0;
    /* put your own code here */
      PLL_init();
      SCI_Init();
   EnableInterrupts;
   printf("\n\r\n\r\n\r9S12ook Version 1.0-xs128 (y nxih h@21cn.com) Build on %s %s\n\r\n\r",__DATE__,__TIME__);
     for(;;)
     {
          printf("\n\r9S12ook-1.0 run times = %d ...",i++);
    delay_ms(1000);
    _FEED_COP(); /* feeds the dog */
   } /* loop forever */
    /* please make sure that you never leave main */
  }
2,在D:\works\9S12_ook-1.0\ook中建立“Drivers”文件夹,及“ rt.c”文件:
  #include <hidef.h>      /* common defines and macros */
  #include "derivative.h"      /* derivative-specific definitions */
  #include <stdio.h>
 
  void SCI_Init(void)
  {
      SCI0CR2=0x2c; //enable Receive Full Interrupt,RX enable,Tx enable
      SCI0BDH=0x00; //SCI0BDL=busclk/(16*SCI0BDL)
      SCI0BDL=0x68; //busclk  8MHz, 9600bps,SCI0BDL=0x68
  }
 
  void TERMIO_PutChar(unsigned char ch)
  {
   while(!(SCI0SR1&0x80)) ;  //keep waiting when not empty
   SCI0DRL=ch;
  }
 
  unsigned char TERMIO_GetChar(void)
  {
     while(!(SCI0SR1&0x80)) ;  //keep waiting when not empty
     return SCI0DRL;
  }

3,在IDE左面“Files”点击右键,选择“Create Group”在向导中填入“Drivers”,点击“OK”,
在IDE左面“Files”下面的“Drivers”上右击选择“Add Files”,打开“D:\works\9S12_ook-1.0\ook\Drivers\ rt.c”;

四,调试9S12_ook工程

1,在菜单中选择“Project”->“Make”编译工程生成目标码;
2,把USBDM 下载器连接上开发板及USB接口,安装下载器自带的TBDML驱动;
3,在IDE工程左面的仿真类型中选择用“TBDML”然后在菜单中选择“Project”->“Debug”调试工程;
4,跳出几个框都确认后就能把目标码下载到CPU中,然后可以在实时仿真界面做单步,全速等操作。

#38 Cortex M0/M3/M4/M7 » 9G-STM32 EWARM开发过程简介之三--移植UCOS-II 2.86 操作系统--缥缈九哥 » 2020-05-09 20:24:13

缥缈九哥
回复: 0

9G-STM32 EWARM开发过程简介之三--移植 OS-II 2.86 操作系统

一,准备 OSII+JLINK+STM32开发板

1,在http://www.mcu123.com/上联系购买支持SWD的JLINK
JLINK ARM仿真器全功能版
http://www.mcu123.com/www/prodshow.asp?ProdId=NO060
一定要购买全功能支持SWD调试的版本。

2,在http://www.manley.com.cn/web/prod t_1.asp?lei_big=仿真学习套件&lei_small=STM3210系列&lan=4上联系购买
EK-STM3210E系列仿真学习套件
http://www.manley.com.cn/web/prod t_neirong_01.asp?pro=280
把开发板上的左下角的CN8旁边的R37,R38焊掉,去掉板上ST-LINK对外加JLINK的SWD接口的干扰。

3,在http://www.micrium.com/st/STM32.html上注册下载 OSII
  OSII-ST-STM32F103ZE-SK.exe
http://www.micrium.com/secure/ OSII-ST-STM32F103ZE-SK.exe
解压后得到“Software”文件包

二,建立EK-STM3210E- OSII工程

1,依照以下网页在D:\works\EK-STM3210E- OSII\建立EWARM的开发工程
EK-STM3210E- OSII及项目名称stm32_ os
http://blog.163.com/yuan_xihua/blog/static/30740544200932931856676/
2,在D:\works\EK-STM3210E- OSII\ software\下建立以下文件夹目录
“ OS-II\Ports”“ OS-II\Source”“ -CPU”“ -LIB”“ -BSP”
3,在IDE工程中建立“ SW”文件组,并在此文件夹中再建立
“ OS-II->Ports”“ OS-II->Source”“ OS-CPU”“ OS-LIB”“ OS-BSp”
4,在左面“Category:”中选择上“C/C++ Complier”,在“Preprocessor”->“Additional include directories:”中添加以下预处理头文件路径
$PROJ_DIR$\..\..\ software\ OS-II\Ports
$PROJ_DIR$\..\..\ software\ OS-II\Source
$PROJ_DIR$\..\..\ software\ -CPU
$PROJ_DIR$\..\..\ software\ -LIB
$PROJ_DIR$\..\..\ software\ -BSP

5,复制源文件

A,复制Software\EvalBoards\ST\STM32F103ZE-SK\IAR\OS-Probe-LCD\app.c到
D:\works\EK-STM3210E- OSII\Source\app.c
把主函数改为:int  os_main (void)
在文件前添加:
#include "stm32f10x.h"
#include "stdio.h"
#include "platform_config.h"
在D:\works\EK-STM3210E- OSII\Source\main.c中有while(1)前加上:
   /* System Clocks Configuration */
   RCC_Configuration();

   /* Configure the GPIO ports */
   GPIO_Configuration();
 
   /* Configure the UART ports */
   UART_Configuration();
 
   /* Setup SysTick Timer for 1 msec interrupts  */
   if (SysTick_Config(SystemFrequency / 1000))
   {
     /* Capture error */
     while (1);
   }

     /* ADC1 Configuration */
   ADC_Configuration();
 
   /* Output a message on Hyperterminal using printf function */
   printf("\n\r\n\r\n\r\n\r");
   printf("*** STM32_ OS2 V2.86 Build by yuanxihua@21cn.com on ("__DATE__ " - " __TIME__ ")\n\r");
   printf("*** STM32_ OS2 V2.86 Rebooting ...\n\r");

  os_main();
并在文件头前加上:
extern int  os_main (void);

B,复制Software\EvalBoards\ST\STM32F103ZE-SK\IAR\BSP下的源文件到
D:\works\EK-STM3210E- OSII\ software\ -BSP
复制Software\ -CPU\ARM-Cortex-M3\IAR 下的源文件到
D:\works\EK-STM3210E- OSII\ software\ -CPU
复制\Software\ -LIB\文件夹到
D:\works\EK-STM3210E- OSII\ software\ -LIB\
复制Software\ OS-II\Ports\arm-cortex-m3\Generic\IAR\下的源文件到
D:\works\EK-STM3210E- OSII\ software\ OS-II\Ports
复制Software\ OS-II\Source\下的源文件到
D:\works\EK-STM3210E- OSII\ software\ OS-II\Source\

6,复制头文件

A,复制Software\EvalBoards\ST\STM32F103ZE-SK\IAR\OS-Probe-LCD\app_cfg.h到
D:\works\EK-STM3210E- OSII\Include\app_cfg.h
去掉文件中下面几行:
//#define  APP_CFG_PROBE_OS_PLUGIN_EN      DEF_ENABLED            /* DEF_ENABLED = Present, DEF_DISABLED = Not Present        */
//#define  APP_CFG_PROBE_COM_EN            DEF_ENABLED
//#define  APP_CFG_LCD_EN                  DEF_ENABLED
//#define  APP_CFG_KSD_EN                  DEF_ENABLED

B,复制Software\EvalBoards\ST\STM32F103ZE-SK\IAR\OS-Probe-LCD\os_cfg.h 到
D:\works\EK-STM3210E- OSII\Include\os_cfg.h
复制Software\EvalBoards\ST\STM32F103ZE-SK\IAR\OS-Probe-LCD\includes.h到
D:\works\EK-STM3210E- OSII\Include\includes.h
复制Software\ -CPU\cpu_def.h到
D:\works\EK-STM3210E- OSII\Include\cpu_def.h

7,去掉编译中出现的找不到stm32f10x_lib.h头文件错误
注释掉所有引用到stm32f10x_lib.h的源文件的这行://#include  <stm32f10x_lib.h>

在D:\works\EK-STM3210E- OSII\ software\ -BSP\bsp.c中注释掉:
  //   FLASH_SetLatency(FLASH_Latency_2);
  //   FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);

  //   FLASH_SetLatency(FLASH_Latency_2);                           /* Embedded Flash Configuration                             */
  //   FLASH_HalfCycleAccessCmd(FLASH_HalfCycleAccess_Disable);
  //   FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);


8,修改中断向量
把D:\works\EK-STM3210E- OSII\Libraries\CMSIS\Core\CM3\startup\iar\startup_stm32f10x_md.s
中的:
   PendSV_Handler  改为:OS_CPU_PendSVHandler
   SysTick_Handler 改为:OS_CPU_SysTickHandler
并在文件前添加:
         EXTERN  OS_CPU_PendSVHandler
         EXTERN  OS_CPU_SysTickHandler

三,移植修改EK-STM3210E- OSII工程
1,在D:\works\EK-STM3210E- OSII\ software\ -BSP\bsp.c中
修改键盘宏定义,键盘初始化及键盘状态读取,使之与EK-STM3210E板硬件相一致;
2,在D:\works\EK-STM3210E- OSII\Source\app.c中
修改接收到按键信息做相应的处理;
       
四,编译调试EK-STM3210E- OSII工程

按常规编译下载调试即可。

#39 Qt/MSVC/MINGW/C++/MFC/GTK+/Delphi/BCB » 移植QtEmbedded-4.5.2到mini2440开发板--缥缈九哥 » 2020-05-09 20:23:22

缥缈九哥
回复: 0

移植QtEmbedded-4.5.2到mini2440开发板

1,下载解压源码:
root@yuanxh-desktop:/# wget http://www.arm123.com.cn/linux/arm-linux-gcc-4.3.2.tgz
root@yuanxh-desktop:/# tar xzvf arm-linux-gcc-4.3.2.tgz
root@yuanxh-desktop:/# mkdir /home/yuanxh/mini2440/
root@yuanxh-desktop:/# cd /home/yuanxh/mini2440/
root@yuanxh-desktop:/home/yuanxh/mini2440# wget ftp://ftp.qtsoftware.com/qt/source/qt-x11-opensource-src-4.5.2.tar.bz2
root@yuanxh-desktop:/home/yuanxh/mini2440# wget ftp://ftp.qtsoftware.com/qt/source/qt-embedded-linux-opensource-src-4.5.2.tar.bz2
root@yuanxh-desktop:/home/yuanxh/mini2440# tar xjvf qt-x11-opensource-src-4.5.2.tar.bz2
root@yuanxh-desktop:/home/yuanxh/mini2440# tar xjvf qt-embedded-linux-opensource-src-4.5.2.tar.bz2

2,配置编译Qt源码:
root@yuanxh-desktop:/home/yuanxh/mini2440# cd qt-x11-opensource-src-4.5.2
root@yuanxh-desktop:/home/yuanxh/mini2440/qt-x11-opensource-src-4.5.2# ./configure
选择o确定开源版本,选择yes接受版权;
root@yuanxh-desktop:/home/yuanxh/mini2440/qt-x11-opensource-src-4.5.2# make
root@yuanxh-desktop:/home/yuanxh/mini2440/qt-x11-opensource-src-4.5.2# make install
root@yuanxh-desktop:/home/yuanxh/mini2440/qt-x11-opensource-src-4.5.2# cd ..
root@yuanxh-desktop:/home/yuanxh/mini2440# cd qt-x11-opensource-src-4.5.2/tools/qvfb
root@yuanxh-desktop:/home/yuanxh/mini2440/qt-x11-opensource-src-4.5.2/tools/qvfb# make
root@yuanxh-desktop:/home/yuanxh/mini2440/qt-x11-opensource-src-4.5.2/tools/qvfb# make install
root@yuanxh-desktop:/home/yuanxh/mini2440/qt-x11-opensource-src-4.5.2/tools/qvfb# cd ../../../
root@yuanxh-desktop:/home/yuanxh/mini2440# file qt-x11-opensource-src-4.5.2/bin/qvfb
3,配置编译QtE源码X86版本:
root@yuanxh-desktop:/home/yuanxh/mini2440# mv qt-embedded-linux-opensource-src-4.5.2 qt-embedded-linux-opensource-src-4.5.2-x86
root@yuanxh-desktop:/home/yuanxh/mini2440# cd qt-embedded-linux-opensource-src-4.5.2-x86
root@yuanxh-desktop:/home/yuanxh/mini2440/qt-embedded-linux-opensource-src-4.5.2-x86# ./configure -prefix /usr/local/Trolltech/QtEmbedded-4.5.2-x86 -embedded x86 -qvfb
选择o确定开源版本,选择yes接受版权;
root@yuanxh-desktop:/home/yuanxh/mini2440/qt-embedded-linux-opensource-src-4.5.2-x86# make
root@yuanxh-desktop:/home/yuanxh/mini2440/qt-embedded-linux-opensource-src-4.5.2-x86# make install
root@yuanxh-desktop:/home/yuanxh/mini2440/qt-embedded-linux-opensource-src-4.5.2-x86# cd ..
root@yuanxh-desktop:/home/yuanxh/mini2440# file /usr/local/Trolltech/QtEmbedded-4.5.2-x86/examples/widgets/analogclock/analogclock
root@yuanxh-desktop:/home/yuanxh/mini2440# cp qt-x11-opensource-src-4.5.2/bin/qvfb /usr/local/Trolltech/QtEmbedded-4.5.2-x86/bin
4,在QVFB上运行DEMO代码
建立配置脚本
root@yuanxh-desktop:/home/yuanxh/mini2440# cd /usr/local/Trolltech/QtEmbedded-4.5.2-x86
root@yuanxh-desktop:/usr/local/Trolltech/QtEmbedded-4.5.2-x86# vi setenv-x86.sh
  添加如下内容:
  QTEDIR=/usr/local/Trolltech/QtEmbedded-4.5.2-x86
  PATH=/usr/local/Trolltech/QtEmbedded-4.5.2-x86/bin:$PATH
  LD_LIBRARY_PATH=/usr/local/Trolltech/QtEmbedded-4.5.2-x86/lib:$LD_LIBRARY_PATH
  保存退出.
root@yuanxh-desktop:/usr/local/Trolltech/QtEmbedded-4.5.2-x86# source setenv-x86.sh
  root@yuanxh-desktop:/usr/local/Trolltech/QtEmbedded-4.5.2-x86# cd /examples/widgets/analogclock
  root@yuanxh-desktop:/usr/local/Trolltech/QtEmbedded-4.5.2-x86/examples/widgets/analogclock# qvfb -width 640 -height 480 &
  root@yuanxh-desktop:/usr/local/Trolltech/QtEmbedded-4.5.2-x86/examples/widgets/analogclock# ./analogclock -qws

5,配置编译QtE源码ARM版本:
root@yuanxh-desktop:/home/yuanxh/mini2440# tar xvjf  qt-embedded-linux-opensource-src-4.5.2.tar.bz2
root@yuanxh-desktop:/home/yuanxh/mini2440# mv qt-embedded-linux-opensource-src-4.5.2 qt-embedded-linux-opensource-src-4.5.2-arm
root@yuanxh-desktop:/home/yuanxh/mini2440# cd qt-embedded-linux-opensource-src-4.5.2-arm/
root@yuanxh-desktop:/home/yuanxh/mini2440/qt-embedded-linux-opensource-src-4.5.2-arm# cd mkspecs/qws/linux-arm-g++/
root@yuanxh-desktop:/home/yuanxh/mini2440/qt-embedded-linux-opensource-src-4.5.2-arm/mkspecs/qws/linux-arm-g++# cp qmake.conf qmake.conf.org
root@yuanxh-desktop:/home/yuanxh/mini2440/qt-embedded-linux-opensource-src-4.5.2-arm/mkspecs/qws/linux-arm-g++# vi qmake.conf
把所有的 arm-linux- 修改为:/usr/local/arm/4.3.2/bin/arm-linux- 后保存
root@yuanxh-desktop:/home/yuanxh/mini2440/qt-embedded-linux-opensource-src-4.5.2-arm/mkspecs/qws/linux-arm-g++# cd ../../../
root@yuanxh-desktop:/home/yuanxh/mini2440/qt-embedded-linux-opensource-src-4.5.2-arm# ./configure -prefix /usr/local/QtEmbedded-4.5.2 -embedded arm -no-webkit
选择o确定开源版本,选择yes接受版权;
root@yuanxh-desktop:/home/yuanxh/mini2440/qt-embedded-linux-opensource-src-4.5.2-arm# make
root@yuanxh-desktop:/home/yuanxh/mini2440/qt-embedded-linux-opensource-src-4.5.2-arm# make install
root@yuanxh-desktop:/home/yuanxh/mini2440/qt-embedded-linux-opensource-src-4.5.2-arm# cd ..
root@yuanxh-desktop:/home/yuanxh/mini2440# file /usr/local/QtEmbedded-4.5.2/examples/widgets/analogclock/analogclock
root@yuanxh-desktop:/home/yuanxh/mini2440# cd /usr/local/
root@yuanxh-desktop:/usr/local# tar czvf QtEmbedded-4.5.2.tgz QtEmbedded-4.5.2
root@yuanxh-desktop:/usr/local# sz QtEmbedded-4.5.2.tgz

6,在ARM板上运行DEMO
建立配置脚本
[root@FriendlyARM /]# mkdir /usr/local/QtEmbedded-4.5.2/
[root@FriendlyARM /]# cd /usr/local/QtEmbedded-4.5.2/
[root@FriendlyARM QtEmbedded-4.5.2]# vi setenv-arm.sh
  添加如下内容:
  export QTDIR=/usr/local/QtEmbedded-4.5.2
  export QPEDIR=/usr/local/QtEmbedded-4.5.2
  export LD_LIBRARY_PATH=$QTDIR/lib:/usr/local/lib:$LD_LIBRARY_PATH
/usr/local/QtEmbedded-4.5.2/analogclock -qws &
  保存退出,并执行。
[root@FriendlyARM QtEmbedded-4.5.2]# mkdir lib/
[root@FriendlyARM QtEmbedded-4.5.2]# mkdir lib/fonts/
把以下的库文件从编译生成的QtEmbedded-4.5.2.tgz文件包的/lib复制到目标板的/usr/local/QtEmbedded-4.5.2/lib
libQtCore.so.4
libQtGui.so.4
libQtNetwork.so.4
libQtSql.so.4
把例子程序analogclock从编译生成的QtEmbedded-4.5.2.tgz文件包的/examples/widgets/analogclock复制到目标板的/usr/local/QtEmbedded-4.5.2/
常用字库文件从从编译生成的QtEmbedded-4.5.2.tgz文件包的lib/fonts/复制到目标板的/usr/local/QtEmbedded-4.5.2/lib/fonts/
......
运行例子
[root@FriendlyARM QtEmbedded-4.5.2]# ./analogclock -qws
[root@FriendlyARM /]# vi /etc/init.d/rcS
在文件中加入:
  /usr/local/QtEmbedded-4.5.2/setenv-arm.sh       
  #/bin/qtopia &
添加自动启动。                       

7,裁剪编译QtE源码ARM版本:
root@yuanxh-desktop:/home/yuanxh/mini2440/qt-embedded-linux-opensource-src-4.5.2-arm# ./configure -prefix /usr/local/QtEmbedded-4.5.2 -embedded arm \
-release -shared -fast -no-largefile -qt-sql-sqlite -no-qt3support -no-xmlpatterns -no-mmx -no-3dnow -no-sse -no-sse2 -no-svg -no-webkit -qt-zlib -qt-gif \
-qt-libtiff -qt-libpng -qt-libmng -qt-libjpeg -make libs -nomake tools -nomake examples -nomake docs -nomake demo -no-nis -no-cups -no-iconv -no-dbus \
-no-openssl -xplatform qws/linux-arm-g++ -little-endian -qt-freetype -depths 16,18 -qt-gfx-linuxfb -no-gfx-transformed -no-gfx-multiscreen \
-no-gfx-vnc -no-gfx-qvfb -qt-kbd-usb -no-glib -qt-mouse-tslib
root@yuanxh-desktop:/home/yuanxh/mini2440/qt-embedded-linux-opensource-src-4.5.2-arm# make
root@yuanxh-desktop:/home/yuanxh/mini2440/qt-embedded-linux-opensource-src-4.5.2-arm# make install

#40 Cortex M0/M3/M4/M7 » 9G-STM32 EWARM开发过程简介之四--移植FSMC的T6963C驱动--缥缈九哥 » 2020-05-09 20:19:50

缥缈九哥
回复: 0

// 9G-STM32 EWARM开发过程简介之四--移植FSMC的T6963C驱动

/*
一,把VDT6与T6963C连接
NOE -> /RD  ;
NWE -> /WR  ;
NE1 -> /CE  ;
A16 -> C/D  ; A16    最近,接线最方便。
PC4 -> /RST ;
D8  -> DB0  ;   D8-D15 最近, 接线最方便。
...
D15 -> DB7  ;

二,把IO配置成FSMC模式
*/

 void LCD_CtrlLinesConfig(void)
 {
   GPIO_InitTypeDef GPIO_InitStructure;
 
   /* Enable FSMC, GPIOC, GPIOD, GPIOE clocks */
   RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC, ENABLE);
 
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE , ENABLE);
 
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 
   /* Set PC.04(LCDRST) as alternate
      function push pull */
   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
   GPIO_Init(GPIOC, &GPIO_InitStructure);
  
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
 
   /* Set PD.04(NOE), PD.05(NWE), PD.07(NE1), PD.08(D13), PD.09(D14), PD.10(D15), PD.11(A16) as alternate
      function push pull */
   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 ;
   GPIO_Init(GPIOD, &GPIO_InitStructure);
 
   /* Set PE.11(D8), PE.12(D9), PE.13(D10), PE.14(D11), PE.15(D12) as alternate function push pull */
   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
   GPIO_Init(GPIOE, &GPIO_InitStructure);
 }

/*       
三,配置FSMC工作模式
*/

 void LCD_FSMCConfig(void)
 {
   FSMC_NORSRAMInitTypeDef  FSMC_NORSRAMInitStructure;
   FSMC_NORSRAMTimingInitTypeDef  p;
 
 /*-- FSMC Configuration ------------------------------------------------------*/
 /*----------------------- SRAM Bank 1 ----------------------------------------*/
   /* FSMC_Bank1_NORSRAM1 configuration */
   p.FSMC_AddressSetupTime = 1;
   p.FSMC_AddressHoldTime = 1;
   p.FSMC_DataSetupTime = 6;
   p.FSMC_BusTurnAroundDuration = 1;
   p.FSMC_CLKDivision = 1;
   p.FSMC_DataLatency = 2;
   p.FSMC_AccessMode = FSMC_AccessMode_A;
 
   /* Color LCD configuration ------------------------------------
      LCD configured as follow:
         - Data/Address MUX = Disable
         - Memory Type = SRAM
         - Data Width = 16bit
         - Write Operation = Enable
         - Extended Mode = Enable
         - Asynchronous Wait = Disable */
   FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM1;
   FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;
   FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_SRAM;
   FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;
   FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable;
   FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;
   FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable;
   FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;
   FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable;
   FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable;
   FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Enable;
   FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable;
   FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &p;
   FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &p;
 
   FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure); 
 
   /* Enable FSMC_Bank1_NORSRAM1 */
   FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM1, ENABLE);
 }

/*
四,定义物理访问地址

*/ //TXEC 240128BDLNW-EY
 // T6963C
 
 /*A16=0 -- dat*/
 #define LCD_DAT_ADDR (*((volatile unsigned char *) 0x60000001))
 /*A16=1 -- cmd*/
 #define LCD_CMD_ADDR (*((volatile unsigned char *) 0x60020001))
 
 #define IMAGE     1
 #define TEXT     0
 #define VISION_PIXEL_LENGTH  240
 #define VISION_PIXEL_WIDTH  128
 #define FRAME_BUFFER_LENGTH  256
 #define FRAME_BUFFER_WIDTH  128

/*
五,定义指令访问接口
*/

//指令&数据读写状态
 static void RWCheck(void)
 {
  while((LCD_CMD_ADDR & 0x03) != 0x03);      //低电平忙
 }
 //数据自动写状态
 void CheckAutoWrite(void)
 {
  while((LCD_CMD_ADDR & 0x08) != 0x08);      //低电平忙
 }
 //屏读/屏考贝出错状态
 void CheckScreen(void)
 {     
  while(LCD_CMD_ADDR & 0x40);      //1出错,0正确
 }
 static void WriteDATA(unsigned char Data)                       
 { 
  RWCheck();
  LCD_DAT_ADDR = Data;
 }
 static unsigned char ReadDATA(void)
 {
  RWCheck();
  return LCD_DAT_ADDR;
 }
 static void WriteCMD0(unsigned char Comd)                 
 {
  RWCheck();
  LCD_CMD_ADDR = Comd;
 }
 static void WriteCMD1(unsigned char Para,unsigned char Comd)
 {
  WriteDATA(Para);
     WriteCMD0(Comd);
 }
 static void WriteCMD2(unsigned char Par1,unsigned char Par2,unsigned char Comd)
 {
  WriteDATA(Par1);
  WriteDATA(Par2); 
     WriteCMD0(Comd);
 }

/*
六,定义API访问接口
*/

 void LCD_Reset(void)
 {
  GPIO_SetBits(GPIOC, GPIO_Pin_4); //置1  LCDRST = 1;
  OSTimeDlyHMSM(0, 0, 0, 10);
     GPIO_ResetBits(GPIOC, GPIO_Pin_4); //清0  LCDRST = 0;
  OSTimeDlyHMSM(0, 0, 0, 50);
     GPIO_SetBits(GPIOC, GPIO_Pin_4); //置1  LCDRST = 1;
  OSTimeDlyHMSM(0, 0, 0, 50);
 }
 
 void STM32_T6963C_Init(void)
 {
   unsigned int i;
 /* Configure the LCD Control pins --------------------------------------------*/
   LCD_CtrlLinesConfig();
 
 /* Configure the FSMC Parallel interface -------------------------------------*/
   LCD_FSMCConfig();
  
 /* initialize sequence  -------------------------------*/
   LCD_Reset();

   WriteCMD2(0x00,0x08,0x42); //设置显示图形首地址
   WriteCMD2((FRAME_BUFFER_LENGTH/8),0x00,0x43); //设置图形显示区域宽度
   WriteCMD0(0x98);   //图形显示开
   WriteCMD0(0x88);   //设定显示方式,图形/文本或的方式
 }
 
 void STM32_T6963C_Clear(void)
 {
  unsigned int i;
  
  WriteCMD2(0x00,0x00,0x24);
  WriteCMD0(0xb0);
   
   for(i=0;i<0x2000;i++)
  {
   WriteCMD1(0x00,0xc0);
  }
  WriteCMD0(0xb2);
 }
 

//设定显示地址函数

 static void LCD_Set_x_y(unsigned char x,unsigned char y,unsigned char mode)
 {
  unsigned int  temp;
  
  temp=(FRAME_BUFFER_LENGTH/8)*y + x/8;
  if(mode==IMAGE)
  {                              //如果图形模式要加上图形区首地址0x0800
   temp+=0x0800;
  }
  WriteCMD2(temp&0xff,temp/256,0x24);
 }
 
 void LCD_Paint_dot(unsigned char x,unsigned char y)
 {
  LCD_Set_x_y(x,y,IMAGE);
  WriteCMD0(0xf8|(0x07&(~(x%8))));
 }
 void LCD_Clear_dot(unsigned char x,unsigned char y)
 {
  LCD_Set_x_y(x,y,IMAGE);
  WriteCMD0(0xf0|(0x07&(~(x%8))));
 }
 void LCD_Paint_line_x(unsigned char y) //图形方式画一条线
 {
  unsigned char i;
 
  LCD_Set_x_y(0,y,IMAGE);
  for(i=0;i<(VISION_PIXEL_LENGTH/8);i++)
  {
   WriteCMD1(0xFF, 0xc0);     //数据写地址不变
  }
 }
 
 void LCD_Paint_line_y(unsigned char x)
 {
  unsigned char i;
 
  for(i=0;i<VISION_PIXEL_WIDTH;i++)
  {
   LCD_Paint_dot(x,i);
  }
 }

/*
七,其它接口自行处理
*/

#41 Cortex M0/M3/M4/M7 » 9G-STM32 EWARM开发过程简介之五--移植FATFS的NANDFLASH驱动--缥缈九哥 » 2020-05-09 20:12:59

缥缈九哥
回复: 0

9G-STM32 EWARM开发过程简介之五--移植FATFS的NANDFLASH驱动

一,建立工程FATFS源码
1,在http://elm-chan.org/fsw/ff/00index_e.html上下载ff007c.zip,并把ff007c.zip里面的
src文件夹复制到D:\works\EK-STM3210E-UCOSII下,并改名为Fatfs;
2,在IDE工程中右击选择“Add Group”建立“FATFS”文件组,并在“FATFS”上右击选择“Add Files”添加
D:\works\EK-STM3210E-UCOSII\Fatfs下的C文件;
3,把D:\works\EK-STM3210E-UCOSII\Fatfs文件夹目录添加到项目头文件搜索路径中,如:
$PROJ_DIR$\..\..\Fatfs

二,移植NANDFLASH驱动接口
1,把stm32f10x_stdperiph_lib_v3.0.0\Project\Examples\FSMC\NAND下的fsmc_nand.c复制到
D:\works\EK-STM3210E-UCOSII\Drivers下,并加入到工程的DRV文件组;
2,把stm32f10x_stdperiph_lib_v3.0.0\Project\Examples\FSMC\NAND下的fsmc_nand.h复制到
D:\works\EK-STM3210E-UCOSII\Include下;
3,在fsmc_nand.c前添加上#include "stm32f10x_conf.h",并把系统中的 "stm32f10x_conf.h"
文件的/* #include "stm32f10x_fsmc.h" */注释打开;

三,修改FATFS的配置文件
1,把D:\works\EK-STM3210E-UCOSII\Fatfs下的ff.h中的宏定义:
  #define _USE_MKFS 0
  #define _CODE_PAGE 932
  #define _FS_RPATH 0
  #define _MAX_SS  512
  修改为:
  #define _USE_MKFS 1
  #define _CODE_PAGE 936
  #define _MAX_SS  2048
  #define _FS_RPATH 1
2,把D:\works\EK-STM3210E-UCOSII\Fatfs下的integer.h的宏定义:
  typedef enum { FALSE = 0, TRUE } BOOL;
  修改为:
  typedef bool BOOL;//typedef enum { FALSE = 0, TRUE } BOOL;
四,修改FATFS的DISK/IO接口
1,把diskio.c复制后改名为nandio.c替换掉工程中的diskio.c,并添加到EWARM的工程中的
  “FATFS”文件组;
2,媒介初始化直接返回正常的0:
  DSTATUS disk_initialize (BYTE drv)
  {  return 0;}
3,媒介状态查询直接返回正常的0:
  DSTATUS disk_status (BYTE drv)
  {  return 0;}
4,取系统系统直接返回0(自己可以按格式修改为真实时间):
  DWORD get_fattime (void)
  {  return 0;}
5,媒介控制接口:

  DRESULT disk_ioctl (BYTE drv,BYTE ctrl, void *buff)
  {
   DRESULT res = RES_OK;
   uint32_t result;

      if (drv){ return RES_PARERR;}
   
      switch(ctrl)
      {
       case CTRL_SYNC:
           break;
    case GET_BLOCK_SIZE:
           *(DWORD*)buff = NAND_BLOCK_SIZE;
           break;
    case GET_SECTOR_COUNT:
           *(DWORD*)buff = (((NAND_MAX_ZONE/2) * NAND_ZONE_SIZE) * NAND_BLOCK_SIZE);
           break;
    case GET_SECTOR_SIZE:
           *(WORD*)buff = NAND_PAGE_SIZE;
           break;
       default:
           res = RES_PARERR;
           break;
   }
      return res;
  }

6,媒介多扇区读接口:

  DRESULT disk_read (BYTE drv,BYTE *buff,DWORD sector,BYTE count)
  {
   uint32_t result;

      if (drv || !count){  return RES_PARERR;}
   result = FSMC_NAND_ReadSmallPage(buff, sector, count);                                               
      if(result & NAND_READY){  return RES_OK; }
      else { return RES_ERROR;  }
  }

7,媒介多扇区写接口:

  #if _READONLY == 0
  DRESULT disk_write (BYTE drv,const BYTE *buff,DWORD sector,BYTE count)
  {
   uint32_t result;
   uint32_t BackupBlockAddr;
   uint32_t WriteBlockAddr;
   uint16_t IndexTmp = 0;
   uint16_t OffsetPage;
  
   /* NAND memory write page at block address*/
   WriteBlockAddr = (sector/NAND_BLOCK_SIZE);
   /* NAND memory backup block address*/
   BackupBlockAddr = (WriteBlockAddr + (NAND_MAX_ZONE/2)*NAND_ZONE_SIZE);
   OffsetPage = sector%NAND_BLOCK_SIZE;
  
      if (drv || !count){  return RES_PARERR;}
   
   /* Erase the NAND backup Block */
      result = FSMC_NAND_EraseBlock(BackupBlockAddr*NAND_BLOCK_SIZE);
  
      /* Backup the NAND Write Block to High zone*/
  
   for (IndexTmp = 0; IndexTmp < NAND_BLOCK_SIZE; IndexTmp++ )
   {
    FSMC_NAND_MoveSmallPage (WriteBlockAddr*NAND_BLOCK_SIZE+IndexTmp,BackupBlockAddr*NAND_BLOCK_SIZE+IndexTmp);
   }
  
   /* Erase the NAND Write Block */
   result = FSMC_NAND_EraseBlock(WriteBlockAddr*NAND_BLOCK_SIZE);
  
      /*return write the block  with modify*/
   for (IndexTmp = 0; IndexTmp < NAND_BLOCK_SIZE; IndexTmp++ )
   {
    if((IndexTmp>=OffsetPage)&&(IndexTmp < (OffsetPage+count)))
    {
     FSMC_NAND_WriteSmallPage((uint8_t *)buff, WriteBlockAddr*NAND_BLOCK_SIZE+IndexTmp, 1);
     buff = (uint8_t *)buff + NAND_PAGE_SIZE;
       }
    else
    {
          FSMC_NAND_MoveSmallPage (BackupBlockAddr*NAND_BLOCK_SIZE+IndexTmp,WriteBlockAddr*NAND_BLOCK_SIZE+IndexTmp);
       }
   }   
   
      if(result == NAND_READY){   return RES_OK;}
      else {   return RES_ERROR;}
  }
  #endif /* _READONLY */

五,调用接口及测试代码
1,调用接口,先初始化FSMC和NANDFLASH:

  //NANDFLASH HY27UF081G2A-TPCB
  #define NAND_HY_MakerID     0xAD
  #define NAND_HY_DeviceID    0xF1
  
  /* Configure the NAND FLASH */
  void NAND_Configuration(void)
  {
   NAND_IDTypeDef NAND_ID;
   
   /* Enable the FSMC Clock */
   RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC, ENABLE);
   
      /* FSMC Initialization */
   FSMC_NAND_Init();
  
   /* NAND read ID command */
   FSMC_NAND_ReadID(&NAND_ID);
    
   /* Verify the NAND ID */
   if((NAND_ID.Maker_ID == NAND_ST_MakerID) && (NAND_ID.Device_ID == NAND_ST_DeviceID))
   {
          printf("ST NANDFLASH");
   }
      else
      if((NAND_ID.Maker_ID == NAND_HY_MakerID) && (NAND_ID.Device_ID == NAND_HY_DeviceID))
   {
          printf("HY27UF081G2A-TPCB");
   }
   printf(" ID = 0x%x%x%x%x \n\r",NAND_ID.Maker_ID,NAND_ID.Device_ID,NAND_ID.Third_ID,NAND_ID.Fourth_ID);
  }

2,然后对媒介格式化,创建读写文件:

  void test_fatfs(void)
  {
      FATFS fs;
   FIL fl;
   FATFS *pfs;
   DWORD clust;
   unsigned int r,w,i;
   FRESULT  res;
   
  // NF_CHKDSK(0,1024);
   display_page(0,0);
   
  // for mount 
   res=f_mount(0,&fs);
   printf("f_mount=%x \n\r",res);
   
  // for format
   //res=f_mkfs(0,1,2048);  //MUST Format for New NANDFLASH !!!
   //printf("f_mkfs=%x \n\r",res);
  
  // for
   pfs=&fs;
   res = f_getfree("/", &clust, &pfs);
   printf("f_getfree=%x \n\r",res);
   printf("\n\r%lu MB total drive space."
       "\n\r%lu MB available.\n\r",
     (DWORD)(pfs->max_clust - 2) * pfs->csize /2/1024,
     clust * pfs->csize /2/1024);
   
  // for read
      res=f_open(&fl,"/test2.dat",FA_OPEN_EXISTING | FA_READ);
      printf("f_open=%x \n\r",res);
   for(i=0;i<2;i++)
   {
    for(r = 0; r < NAND_PAGE_SIZE; r++)
    {
     RxBuffer[r]= 0xff;
    }
    
    res=f_read(&fl,RxBuffer,NAND_PAGE_SIZE,&r);
    printf("f_read=%x \n\r",res);
    if(res || r == 0)break;
    for(r = 0; r < NAND_PAGE_SIZE; r++)
       {
           printf("D[%08x]=%02x ",(i*NAND_PAGE_SIZE+r),RxBuffer[r]);
           if((r%8)==7)
           {printf("\n\r");}
       }
      
   }
   f_close(&fl);
  // for write
   res=f_open(&fl,"/test2.dat",FA_CREATE_ALWAYS | FA_WRITE);
   printf("f_open=%x \n\r",res);
   for(i=0;i<2;i++)
   {
    for(w = 0; w < NAND_PAGE_SIZE; w++)
    {
     TxBuffer[w]=((w<<0)&0xff);
    }
          res=f_write(&fl,TxBuffer,NAND_PAGE_SIZE,&w);
          printf("f_write=%x \n\r",res);
    if(res || w<NAND_PAGE_SIZE)break;
    
   }
   f_close(&fl);
   
  // for umount
   f_mount(0,NULL);
  }

六,编写NANDFLASH接口
1,fsmc_nand.c文件:

  /* Includes ------------------------------------------------------------------*/
  #include "fsmc_nand.h"
  #include "stm32f10x_conf.h"
  
  /** @addtogroup StdPeriph_Examples
    * @{
    */
  
  /** @addtogroup FSMC_NAND
    * @{
    */
  
  /* Private typedef -----------------------------------------------------------*/
  /* Private define ------------------------------------------------------------*/
  
  #define FSMC_Bank_NAND     FSMC_Bank2_NAND
  #define Bank_NAND_ADDR     Bank2_NAND_ADDR
  #define Bank2_NAND_ADDR    ((uint32_t)0x70000000)
  
  /* Private macro -------------------------------------------------------------*/
  /* Private variables ---------------------------------------------------------*/
  /* Private function prototypes -----------------------------------------------*/
  /* Private functions ---------------------------------------------------------*/
  
  /**
    * @brief  Configures the FSMC and GPIOs to interface with the NAND memory.
    *   This function must be called before any write/read operation
    *   on the NAND.
    * @param  None
    * @retval : None
    */
  void FSMC_NAND_Init(void)
  {
    GPIO_InitTypeDef GPIO_InitStructure;
    FSMC_NANDInitTypeDef FSMC_NANDInitStructure;
    FSMC_NAND_PCCARDTimingInitTypeDef  p;
   
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE |
                           RCC_APB2Periph_GPIOF | RCC_APB2Periph_GPIOG, ENABLE);
   
  /*-- GPIO Configuration ------------------------------------------------------*/
  /* CLE, ALE, D0->D3, NOE, NWE and NCE2  NAND pin configuration  */
    GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_14 | GPIO_Pin_15 | 
                                   GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5 |
                                   GPIO_Pin_7;                                 
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  
    GPIO_Init(GPIOD, &GPIO_InitStructure);
  
  /* D4->D7 NAND pin configuration  */ 
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10;
  
    GPIO_Init(GPIOE, &GPIO_InitStructure);
  
  
  /* NWAIT NAND pin configuration */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;          
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
  
    GPIO_Init(GPIOD, &GPIO_InitStructure);
  
  /* INT2 NAND pin configuration */ 
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;          
    GPIO_Init(GPIOG, &GPIO_InitStructure);
  
    /*-- FSMC Configuration ------------------------------------------------------*/
    p.FSMC_SetupTime = 0x1;
    p.FSMC_WaitSetupTime = 0x3;
    p.FSMC_HoldSetupTime = 0x2;
    p.FSMC_HiZSetupTime = 0x1;
  
    FSMC_NANDInitStructure.FSMC_Bank = FSMC_Bank2_NAND;
    FSMC_NANDInitStructure.FSMC_Waitfeature = FSMC_Waitfeature_Enable;
    FSMC_NANDInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_8b;
    FSMC_NANDInitStructure.FSMC_ECC = FSMC_ECC_Enable;
    FSMC_NANDInitStructure.FSMC_ECCPageSize = FSMC_ECCPageSize_512Bytes;
    FSMC_NANDInitStructure.FSMC_TCLRSetupTime = 0x00;
    FSMC_NANDInitStructure.FSMC_TARSetupTime = 0x00;
    FSMC_NANDInitStructure.FSMC_CommonSpaceTimingStruct = &p;
    FSMC_NANDInitStructure.FSMC_AttributeSpaceTimingStruct = &p;
  
    FSMC_NANDInit(&FSMC_NANDInitStructure);
  
    /* FSMC NAND Bank Cmd Test */
    FSMC_NANDCmd(FSMC_Bank2_NAND, ENABLE);
  }
   
  /**
    * @brief  Reads NAND memory's ID.
    * @param  NAND_ID: pointer to a NAND_IDTypeDef structure which will hold
    *                  the Manufacturer and Device ID. 
    * @retval : None
    */
  void FSMC_NAND_ReadID(NAND_IDTypeDef* NAND_ID)
  {
    uint32_t data = 0;
  
    /* Send Command to the command area */  
    *(__IO uint8_t *)(Bank_NAND_ADDR | CMD_AREA)  = NAND_CMD_READID;
    /* Send Address to the address area */
    *(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = NAND_CMD_IDADDR;
  
     /* Sequence to read ID from NAND flash */ 
     data = *(__IO uint32_t *)(Bank_NAND_ADDR | DATA_AREA);
  
     NAND_ID->Maker_ID   = DATA_1st_CYCLE (data);
     NAND_ID->Device_ID  = DATA_2nd_CYCLE (data);
     NAND_ID->Third_ID   = DATA_3rd_CYCLE (data);
     NAND_ID->Fourth_ID  = DATA_4th_CYCLE (data); 
  }
  /**
    * @brief  This routine is for move one 2048 Bytes Page size to an other 2048 Bytes Page.
    *         the copy-back program is permitted just between odd address pages or even address pages.
    * @param  SourcePageAddress: Source page address
    * @param  TargetPageAddress: Target page address
    * @retval : New status of the NAND operation. This parameter can be:
    *              - NAND_TIMEOUT_ERROR: when the previous operation generate
    *                a Timeout error
    *              - NAND_READY: when memory is ready for the next operation
    *                And the new status of the increment address operation. It can be:
    *              - NAND_VALID_ADDRESS: When the new address is valid address
    *              - NAND_INVALID_ADDRESS: When the new address is invalid address 
    */
  uint32_t FSMC_NAND_MoveSmallPage(uint32_t SourcePageAddress, uint32_t TargetPageAddress)
  {
    uint32_t status = NAND_READY ;
    uint32_t data = 0xff;
  
      /* Page write command and address */
      *(__IO uint8_t *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_MOVE0;
  
      *(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_1st_CYCLE(SourcePageAddress); 
      *(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_2nd_CYCLE(SourcePageAddress); 
      *(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_3rd_CYCLE(SourcePageAddress); 
      *(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_4th_CYCLE(SourcePageAddress);
  
      *(__IO uint8_t *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_MOVE1;
  
      while( GPIO_ReadInputDataBit(GPIOG, GPIO_Pin_6) == 0 );
  
       *(__IO uint8_t *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_MOVE2;
  
      *(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_1st_CYCLE(TargetPageAddress); 
      *(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_2nd_CYCLE(TargetPageAddress); 
      *(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_3rd_CYCLE(TargetPageAddress); 
      *(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_4th_CYCLE(TargetPageAddress);
  
      *(__IO uint8_t *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_MOVE3;
  
      while( GPIO_ReadInputDataBit(GPIOG, GPIO_Pin_6) == 0 );  
  
      /* Check status for successful operation */
      status = FSMC_NAND_GetStatus();
     
   data = *(__IO uint8_t *)(Bank_NAND_ADDR | DATA_AREA);
   if(!(data&0x1)) status = NAND_READY;
     
   return (status);
  }
  /**
    * @brief  This routine is for writing one or several 2048 Bytes Page size.
    * @param  pBuffer: pointer on the Buffer containing data to be written
    * @param  PageAddress: First page address
    * @param  NumPageToWrite: Number of page to write 
    * @retval : New status of the NAND operation. This parameter can be:
    *              - NAND_TIMEOUT_ERROR: when the previous operation generate
    *                a Timeout error
    *              - NAND_READY: when memory is ready for the next operation
    *                And the new status of the increment address operation. It can be:
    *              - NAND_VALID_ADDRESS: When the new address is valid address
    *              - NAND_INVALID_ADDRESS: When the new address is invalid address 
    */
  
  uint32_t FSMC_NAND_WriteSmallPage(uint8_t *pBuffer, uint32_t PageAddress, uint32_t NumPageToWrite)
  {
    uint32_t index = 0x00, numpagewritten = 0x00,addressstatus = NAND_VALID_ADDRESS;
    uint32_t status = NAND_READY, size = 0x00;
    uint32_t data = 0xff;
  
    while((NumPageToWrite != 0x00) && (addressstatus == NAND_VALID_ADDRESS) && (status == NAND_READY))
    {
      /* Page write command and address */
      *(__IO uint8_t *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_WRITE0;
  
      *(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_1st_CYCLE(PageAddress); 
      *(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_2nd_CYCLE(PageAddress); 
      *(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_3rd_CYCLE(PageAddress); 
      *(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_4th_CYCLE(PageAddress);
     
      /* Calculate the size */
      size = NAND_PAGE_SIZE + (NAND_PAGE_SIZE * numpagewritten);
  
      /* Write data */
      for(; index < size; index++)
      {
        *(__IO uint8_t *)(Bank_NAND_ADDR | DATA_AREA) = pBuffer[index];
      }
     
      *(__IO uint8_t *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_WRITE1;
  
      while( GPIO_ReadInputDataBit(GPIOG, GPIO_Pin_6) == 0 );
     
      /* Check status for successful operation */
      status = FSMC_NAND_GetStatus();
     
   data = *(__IO uint8_t *)(Bank_NAND_ADDR | DATA_AREA);
   if(!(data&0x1)) status = NAND_READY;
     
      if(status == NAND_READY)
      {
        numpagewritten++; NumPageToWrite--;
  
        /* Calculate Next small page Address */
        if(PageAddress++ > (NAND_MAX_ZONE*NAND_ZONE_SIZE*NAND_BLOCK_SIZE))
        { addressstatus = NAND_INVALID_ADDRESS;} 
      }   
    }
   
    return (status | addressstatus);
  }
   
  /**
    * @brief  This routine is for sequential read from one or several
    *         2048 Bytes Page size. 
    * @param  pBuffer: pointer on the Buffer to fill
    * @param  PageAddress: First page address
    * @param  NumPageToRead: Number of page to read 
    * @retval : New status of the NAND operation. This parameter can be:
    *              - NAND_TIMEOUT_ERROR: when the previous operation generate
    *                a Timeout error
    *              - NAND_READY: when memory is ready for the next operation
    *                And the new status of the increment address operation. It can be:
    *              - NAND_VALID_ADDRESS: When the new address is valid address
    *              - NAND_INVALID_ADDRESS: When the new address is invalid address
    */
   
   
  uint32_t FSMC_NAND_ReadSmallPage(uint8_t *pBuffer, uint32_t PageAddress, uint32_t NumPageToRead)
  {
    uint32_t index = 0x00, numpageread = 0x00, addressstatus = NAND_VALID_ADDRESS;
    uint32_t status = NAND_READY, size = 0x00;
  
   *(__IO uint8_t *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_READ1;
     
   while((NumPageToRead != 0x0) && (addressstatus == NAND_VALID_ADDRESS))
     {   
       /* Page Read command and page address */
    
    *(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_1st_CYCLE(PageAddress);
       *(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_2nd_CYCLE(PageAddress);
       *(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_3rd_CYCLE(PageAddress);
       *(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_4th_CYCLE(PageAddress);
         
       *(__IO uint8_t *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_READ2;
  
       while( GPIO_ReadInputDataBit(GPIOG, GPIO_Pin_6) == 0 );
      
       /* Calculate the size */
       size = NAND_PAGE_SIZE + (NAND_PAGE_SIZE * numpageread);
      
       /* Get Data into Buffer */   
       for(; index < size; index++)
       {
         pBuffer[index]= *(__IO uint8_t *)(Bank_NAND_ADDR | DATA_AREA);
       }
   
       numpageread++; NumPageToRead--;
  
       /* Calculate page address */              
    if(PageAddress++ > (NAND_MAX_ZONE*NAND_ZONE_SIZE*NAND_BLOCK_SIZE))
    { addressstatus = NAND_INVALID_ADDRESS;}
   }
  
     status = FSMC_NAND_GetStatus();
   
     return (status | addressstatus);
  }
   
  /**
    * @brief  This routine erase complete block from NAND FLASH
    * @param  PageAddress: Any address into block to be erased
    * @retval :New status of the NAND operation. This parameter can be:
    *              - NAND_TIMEOUT_ERROR: when the previous operation generate
    *                a Timeout error
    *              - NAND_READY: when memory is ready for the next operation
    */
   
  uint32_t FSMC_NAND_EraseBlock(uint32_t PageAddress)
  {
   uint32_t data = 0xff, status = NAND_ERROR;
   
    *(__IO uint8_t *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_ERASE0;
  
    *(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_3rd_CYCLE(PageAddress);
    *(__IO uint8_t *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_4th_CYCLE(PageAddress);
    
    *(__IO uint8_t *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_ERASE1;
  
    while( GPIO_ReadInputDataBit(GPIOG, GPIO_Pin_6) == 0 );
  
    /* Read status operation ------------------------------------ */ 
    FSMC_NAND_GetStatus();
  
    data = *(__IO uint8_t *)(Bank_NAND_ADDR | DATA_AREA);
   
    if(!(data&0x1)) status = NAND_READY;
     
    return (status);
  }
  
  /**
    * @brief  This routine reset the NAND FLASH
    * @param  None
    * @retval :NAND_READY
    */
  
  uint32_t FSMC_NAND_Reset(void)
  {
    *(__IO uint8_t *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_RESET;
  
    return (NAND_READY);
  }
  
  /**
    * @brief  Get the NAND operation status
    * @param  None
    * @retval :New status of the NAND operation. This parameter can be:
    *              - NAND_TIMEOUT_ERROR: when the previous operation generate
    *                a Timeout error
    *              - NAND_READY: when memory is ready for the next operation   
    */
   
   
  uint32_t FSMC_NAND_GetStatus(void)
  {
    uint32_t timeout = 0x1000000, status = NAND_READY;
  
    status = FSMC_NAND_ReadStatus();
  
    /* Wait for a NAND operation to complete or a TIMEOUT to occur */
    while ((status != NAND_READY) &&( timeout != 0x00))
    {
       status = FSMC_NAND_ReadStatus();
       timeout --;     
    }
  
    if(timeout == 0x00)
    {         
      status =  NAND_TIMEOUT_ERROR;     
    }
  
    /* Return the operation status */
    return (status);     
  }
   
  /**
    * @brief  Reads the NAND memory status using the Read status command
    * @param  None
    * @retval :The status of the NAND memory. This parameter can be:
    *              - NAND_BUSY: when memory is busy
    *              - NAND_READY: when memory is ready for the next operation   
    *              - NAND_ERROR: when the previous operation gererates error    
    */
   
  uint32_t FSMC_NAND_ReadStatus(void)
  {
    uint32_t data = 0x00, status = NAND_BUSY;
  
    /* Read status operation ------------------------------------ */
    *(__IO uint8_t *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_STATUS;
    data = *(__IO uint8_t *)(Bank_NAND_ADDR);
  
    if((data & NAND_ERROR) == NAND_ERROR)
    {
      status = NAND_ERROR;
    }
    else if((data & NAND_READY) == NAND_READY)
    {
      status = NAND_READY;
    }
    else
    {
      status = NAND_BUSY;
    }
   
    return (status);
  }

2,fsmc_nand.h文件:

  /* Define to prevent recursive inclusion -------------------------------------*/
  #ifndef __FSMC_NAND_H
  #define __FSMC_NAND_H
  
  /* Includes ------------------------------------------------------------------*/
  #include "stm32f10x.h"
  
  /* Exported types ------------------------------------------------------------*/
  typedef struct
  {
    uint8_t Maker_ID;
    uint8_t Device_ID;
    uint8_t Third_ID;
    uint8_t Fourth_ID;
  }NAND_IDTypeDef;
  
  typedef struct
  {
    uint16_t Zone;
    uint16_t Block;
    uint16_t Page;
  } NAND_ADDRESS;
  
  /* Exported constants --------------------------------------------------------*/
  /* NAND Area definition  for STM3210E-EVAL Board RevD */
  #define CMD_AREA                   (uint32_t)(1<<16)  /* A16 = CLE high */
  #define ADDR_AREA                  (uint32_t)(1<<17)  /* A17 = ALE high */
  #define DATA_AREA                  ((uint32_t)0x00000000)
  
  /* FSMC NAND memory command */
  #define NAND_CMD_READ1             ((uint8_t)0x00)
  #define NAND_CMD_READ2            ((uint8_t)0x30)
  
  #define NAND_CMD_WRITE0            ((uint8_t)0x80)
  #define NAND_CMD_WRITE1            ((uint8_t)0x10)
  
  #define NAND_CMD_MOVE0             ((uint8_t)0x00)
  #define NAND_CMD_MOVE1             ((uint8_t)0x35)
  #define NAND_CMD_MOVE2             ((uint8_t)0x85)
  #define NAND_CMD_MOVE3             ((uint8_t)0x10)
   
  #define NAND_CMD_ERASE0            ((uint8_t)0x60)
  #define NAND_CMD_ERASE1            ((uint8_t)0xD0) 
  
  #define NAND_CMD_READID            ((uint8_t)0x90)
  #define NAND_CMD_IDADDR            ((uint8_t)0x00)
   
  #define NAND_CMD_STATUS            ((uint8_t)0x70)
  #define NAND_CMD_RESET             ((uint8_t)0xFF)
  
  /* NAND memory status */
  #define NAND_VALID_ADDRESS         ((uint32_t)0x00000100)
  #define NAND_INVALID_ADDRESS       ((uint32_t)0x00000200)
  #define NAND_TIMEOUT_ERROR         ((uint32_t)0x00000400)
  #define NAND_BUSY                  ((uint32_t)0x00000000)
  #define NAND_ERROR                 ((uint32_t)0x00000001)
  #define NAND_READY                 ((uint32_t)0x00000040)
  
  /* FSMC NAND memory parameters */
  //#define NAND_PAGE_SIZE             ((uint16_t)0x0200) /* 512 bytes per page w/o Spare Area */
  //#define NAND_BLOCK_SIZE            ((uint16_t)0x0020) /* 32x512 bytes pages per block */
  //#define NAND_ZONE_SIZE             ((uint16_t)0x0400) /* 1024 Block per zone */
  //#define NAND_SPARE_AREA_SIZE       ((uint16_t)0x0010) /* last 16 bytes as spare area */
  //#define NAND_MAX_ZONE              ((uint16_t)0x0004) /* 4 zones of 1024 block */
  
  /* FSMC NAND memory HY27UF081G2A-TPCB parameters */
  #define NAND_PAGE_SIZE             ((uint16_t)0x0800) /* 2048 bytes per page w/o Spare Area */
  #define NAND_BLOCK_SIZE            ((uint16_t)0x0040) /* 64x2048 bytes pages per block */
  #define NAND_ZONE_SIZE             ((uint16_t)0x0200) /* 512 Block per zone */
  #define NAND_SPARE_AREA_SIZE       ((uint16_t)0x0040) /* last 64 bytes as spare area */
  #define NAND_MAX_ZONE              ((uint16_t)0x0002) /* 2 zones of 1024 block */
  
  /* FSMC NAND memory data computation */
  #define DATA_1st_CYCLE(DATA)       (uint8_t)((DATA)& 0xFF)               /* 1st data cycle */
  #define DATA_2nd_CYCLE(DATA)       (uint8_t)(((DATA)& 0xFF00) >> 8)      /* 2nd data cycle */
  #define DATA_3rd_CYCLE(DATA)       (uint8_t)(((DATA)& 0xFF0000) >> 16)   /* 3rd data cycle */
  #define DATA_4th_CYCLE(DATA)       (uint8_t)(((DATA)& 0xFF000000) >> 24) /* 4th data cycle */
  
  /* FSMC NAND memory HY27UF081G2A-TPCB address computation */
  #define ADDR_1st_CYCLE(PADDR)       (uint8_t)(0x0)          /* 1st addressing cycle */
  #define ADDR_2nd_CYCLE(PADDR)       (uint8_t)(0x0)     /* 2nd addressing cycle */
  #define ADDR_3rd_CYCLE(PADDR)       (uint8_t)(PADDR & 0xFF)      /* 3rd addressing cycle */
  #define ADDR_4th_CYCLE(PADDR)       (uint8_t)((PADDR>>8) & 0xFF) /* 4th addressing cycle */
  
  /* Exported macro ------------------------------------------------------------*/
  /* Exported functions ------------------------------------------------------- */
  void FSMC_NAND_Init(void);
  void FSMC_NAND_ReadID(NAND_IDTypeDef* NAND_ID);
  uint32_t FSMC_NAND_WriteSmallPage(uint8_t *pBuffer, uint32_t Address, uint32_t NumPageToWrite);
  uint32_t FSMC_NAND_ReadSmallPage (uint8_t *pBuffer, uint32_t Address, uint32_t NumPageToRead);
  uint32_t FSMC_NAND_MoveSmallPage (uint32_t SourcePageAddress, uint32_t TargetPageAddress);
  //uint32_t FSMC_NAND_WriteSpareArea(uint8_t *pBuffer, NAND_ADDRESS Address, uint32_t NumSpareAreaTowrite);
  //uint32_t FSMC_NAND_ReadSpareArea(uint8_t *pBuffer, NAND_ADDRESS Address, uint32_t NumSpareAreaToRead);
  uint32_t FSMC_NAND_EraseBlock(uint32_t Address);
  uint32_t FSMC_NAND_Reset(void);
  uint32_t FSMC_NAND_GetStatus(void);
  uint32_t FSMC_NAND_ReadStatus(void);
  //uint32_t FSMC_NAND_AddressIncrement(NAND_ADDRESS* Address);
  
  #endif /* __FSMC_NAND_H */

七,NFTL代码层
有关NFTL代码,自行处理。

#42 Cortex M0/M3/M4/M7 » 9G-STM32 MDK-ARM开发过程简介--缥缈九哥 » 2020-05-09 20:11:22

缥缈九哥
回复: 6

9G-STM32 MDK-ARM开发过程简介

一,准备MDK-ARM+JLINK+STM32软件包

1,在http://www.mcu123.com/news/Soft/embsof/arm/200908/505.html
    下载RealView MDK-ARM 3.80a(MDK-ARM V3.80a,MDK3.80a)版本
    mdk380a_mcu123.rar
    http://esoft.mcu123.com/MCU123_temp_0080309@/arm/mdk380a_mcu123.rar
    (注册机自行查找,安装过程略)
2,在http://www.segger.com/cms/jlink-software.html
    下载Software and documentation pack V4.08l软件
Setup_JLinkARM_V408l.zip
http://www.segger.com/cms/admin/uploads/userfiles/file/J-Link/Setup_JLinkARM_V408l.zip
    (JLINK自行购买,安装过程略)
3,在http://www.st.com/mcu/familiesdocs-110.html
    下载ARM-based 32-bit MCU STM32F10xxx standard peripheral library
    stm32f10x_stdperiph_lib.zip
http://www.st.com/stonline/products/support/micro/files/stm32f10x_stdperiph_lib.zip
       
二,建立STM32工程

1,解压stm32f10x_stdperiph_lib.zip软件包,把其中的“Libraries”和“Project”文件夹复制到“D:\works\EK-STM3210E-MDK\”,
在“D:\works\EK-STM3210E-MDK\”下建立“Drivers”、“Include”和“Source”空文件夹,在“D:\works\lccd-1.0.0\Project”
下建立“Stm32f103”空文件夹,把“Project\Template”下的C文件复制到“Source”和H文件复制到“Include”;
2,在Keil uVision3菜单中“Project”->“New uVision Project”打开“Create New Project”窗口,选择项目工程存储路径
“D:\works\EK-STM3210E-MDK\Project\Stm32f103”填写项目文件名“stm32.uv2",选择“保存”后自动打开“Select Device for
Target "Target 1"”窗口,在左面“CPU”页面下的“Data base”点开“STMicroelectronics”前面的“+”选择上“STM32F103ZD”
点击“OK”再确定“是”;
3,在Keil uVision3菜单中“Project”->“New Project Workspace”打开“Create New Multi Project Workspace”窗口,选择项目
工作区存储路径“D:\works\EK-STM3210E-MDK\Project\Stm32f103”填写工作区文件名“stm32.mpw",点击“保存”打开
“Create New Multi-Project Workspace”窗口,点击插入项目,然后选择到刚才建立的“stm32.uv2"再点“OK”“确定”
即可建立一个新的 Workspace;
4,在Keil uVision3菜单中“Project”->“Manage”选择“Project "stm32" Components”打开“Components Environment and Books”窗口,
把“Target 1”改为“EK-STM3210E”把“Source Group 1”以为“BOOT”点击“OK”;并在“Groups”下建立“SRC”,“DRV”,“SRC”,
“INC”,“SDRV”等 目录;
5,在Keil uVision3的左面“Workspace”窗口下面的“BOOT”上右击鼠标,选择“Add Files to Group "BOOT"”选择上文件
“D:\works\EK-STM3210E-MDK\Libraries\CMSIS\Core\CM3”文件夹下的“core_cm3.c”和“system_stm32f10x.c”文件,和
D:\works\EK-STM3210E-MDK\Libraries\CMSIS\Core\CM3\startup\arm文件夹下的“startup_stm32f10x_hd.s”后点击“CLOSE”退出;
6,在Keil uVision3的左面“Workspace”窗口下面的“SDRV”上右击鼠标,选择“Add Files to Group "SDRV"”选择上文件
“D:\works\EK-STM3210E-MDK\Libraries\STM32F10x_StdPeriph_Driver\src”文件夹下的所有C文件后点击“CLOSE”退出;
7,在Keil uVision3的左面“Workspace”窗口下面的“SRC”上右击鼠标,选择“Add Files to Group "SRC"”选择上文件
“D:\works\EK-STM3210E-MDK\Source”文件夹下的“main.c”和“stm32f10x_it.c”文件后点击“CLOSE”退出;
8,在Keil uVision3的左面“Workspace”窗口下面的“DRV”上右击鼠标,选择“Add Files to Group "DRV"”选择上文件
“D:\works\EK-STM3210E-MDK\Source”文件夹下的“serial.c”文件后点击“CLOSE”退出;

三,配置STM32工程

在Keil uVision3的左面“Workspace”窗口下面的“EK-STM3210E”右击鼠标,选择“Options for Target "EK-STM3210E"”窗口;

1,在页面“Device”中选择上“STMicroelectronics”下面的STM32F103ZD”,
在页面“TarGet”中选择上“USE microLIB”;
2,在页面“Output”中选择上“Select Folder for Objects...”,在文件夹选择框中指定到路径:
D:\works\EK-STM3210E-MDK\Project\Stm32f103\obj 后点击“OK”;并勾选上Create HEX File,
产生“Debug information”浏览“Browse information”;
3,在页面“Listing”中选择上“Select Folder for Listing...”,在文件夹选择框中指定到路径:
D:\works\EK-STM3210E-MDK\Project\Stm32f103\lst 后点击“OK”;并勾选上C Compiler Listing
和 C Preprocessor Listing (看看自己是否需要);

4,在页面“C/C++”中的“Include Paths ”,中添加:
..\..\Libraries\STM32F10x_StdPeriph_Driver\inc
..\..\Libraries\CMSIS\Core\CM3
..\..\Include
在页面“C/C++”中的“Preprocessor Symbols”,中添加:
USE_STDPERIPH_DRIVER, USE_FULL_ASSERT, STM32F10X_HD,USE_STM3210C_EVAL
5,在页面“ASM”中的“Include Paths ”,中添加:
..\..\Libraries\STM32F10x_StdPeriph_Driver\inc
..\..\Libraries\CMSIS\Core\CM3
..\..\Include
在页面“ASM”中的“Preprocessor Symbols”,中添加:
USE_STDPERIPH_DRIVER, USE_FULL_ASSERT, STM32F10X_HD,USE_STM3210C_EVAL
6,在页面“Debug”中选择右边的硬件仿真功能的“Cortex-M3 J-LINK”,并点开右面的“Settings”配置页面,选择SW接口并把速度改成2M;
在“Flash Download”的编程算法选择上“STM32F10x High-density Flash”;

7,在页面“Utlites”中硬件FLASH编程工具“Cortex-M3 J-LINK”,并点开右面的“Settings”配置页面,选择SW接口并把速度改成2M;
在“Flash Download”的编程算法选择上“STM32F10x High-density Flash”;

四,修改STM32工程
(待续)


附件:
1,serial.c 文件

/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
#include "stm32f10x_conf.h"
#include <stdio.h>
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
 USART_InitTypeDef USART_InitStructure;
 GPIO_InitTypeDef GPIO_InitStructure;

/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
void UART_Configuration(void)
{
/* Enable USART1 clocks */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE);

  /* Configure USART1_Tx as alternate function push-pull */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  /* Configure USART1_Rx as input floating */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
  /* USARTx configured as follow:
        - BaudRate = 115200 baud 
        - Word Length = 8 Bits
        - One Stop Bit
        - No parity
        - Hardware flow control disabled (RTS and CTS signals)
        - Receive and transmit enabled
  */
  USART_InitStructure.USART_BaudRate = 115200;
  USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  USART_InitStructure.USART_StopBits = USART_StopBits_1;
  USART_InitStructure.USART_Parity = USART_Parity_No;
  USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

//  STM_EVAL_COMInit(COM1, &USART_InitStructure);
  /* Configure the USARTx */
  USART_Init(USART1, &USART_InitStructure);
  /* Enable the USARTx */
  USART_Cmd(USART1, ENABLE);
}

/**
  * @brief  Retargets the C library printf function to the USART.
  * @param  None
  * @retval None
  */
int fputc(int ch, FILE *f)
{
  /* Place your implementation of fputc here */
  /* e.g. write a character to the USART */
  USART_SendData(USART1, (uint8_t) ch);

  /* Loop until the end of transmission */
  while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET)
  {}

  return ch;
}

#ifdef  USE_FULL_ASSERT

/**
  * @brief  Reports the name of the source file and the source line number
  *   where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t* file, uint32_t line)
{
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  printf("Wrong parameters value: file %s on line %d\r\n", file, line);
  /* Infinite loop */
  while (1)
  {
  }
}
#endif
/******************* (C) COPYRIGHT 2009 STMicroelectronics *****END OF FILE****/

2,main.c文件

/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
#include "stm32f10x_conf.h"
#include <stdio.h>
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
extern void UART_Configuration(void);
/**
  * @brief  Main program.
  * @param  None
  * @retval None
  */
int main(void)
{
 /* Setup STM32 system (clock, PLL and Flash configuration) */
  SystemInit();

  UART_Configuration();

  /* Output a message on Hyperterminal using printf function */
  printf("\n\r\n\r\n\r\n\r");
  printf("*** STM32-MDK V1.0 Build by yuanxihua@21cn.com on ("__DATE__ " - " __TIME__ ")\n\r");
  printf("*** STM32-MDK V1.0 Rebooting ...\n\r");

  /* Add your application code here
     */

  /* Infinite loop */
  while (1)
  {
  }
}
/******************* (C) COPYRIGHT 2009 STMicroelectronics *****END OF FILE****/

#43 ST/STM8/STM8S/STM8L » 9G-STM8 CXSTM8使用过程简介 --缥缈九哥 » 2020-05-09 20:10:11

缥缈九哥
回复: 1

9G-STM8 CXSTM8使用过程简介

一,准备STVD+CXSTM8+STM8软件包

1,在http://www.st.com/mcu/familiesdocs-120.html
    下载ST Visual Develop (STVD) 4.1.3 and ST Visual Programmer (STVP) 3.1.3 版本
    sttoolset.exe
    http://www.st.com/stonline/products/support/micro/files/sttoolset.exe
   
2,在http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=3229327&bbs_page_no=1&bbs_id=3020
    下载CXSTM8 4.2.8 无需License,去除16K限制软件
CXSTM8.rar
http://cache.ourdev.cn/bbs_upload247021/files_12/ourdev_423629.rar
还有补丁
Cosmic.rar
http://cache.ourdev.cn/bbs_upload247021/files_13/ourdev_424179.rar
(试用限制版本http://www.cosmicsoftware.com/cxstm8_16k.exe)

3,在http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=3600882&bbs_page_no=7&bbs_id=3020
    下载STM8S105S4-PKT演示代码.zip
    ourdev_484758.zip
http://cache.ourdev.cn/bbs_upload247021/files_19/ourdev_484758.zip
STM8S105S4-PKT演示代码使用说明.pdf
ourdev_484759.pdf
http://cache.ourdev.cn/bbs_upload247021/files_19/ourdev_484759.pdf
其它相关资源:
如何开始STM8S系列单片机的开发
http://images.stmicroelectronics.com.cn/stonline/mcu/images/STM8S_development.pdf
STM8S体验系统板STM8S105S4-PKT用户手册
http://download.ourdev.cn/bbs_upload247021/files_22/ourdev_506732.pdf
开发板套件见连接:
http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=3723427&bbs_page_no=1&bbs_id=3020

4,其它文档的下载地址如下:
http://www.st.com/mcu/familiesdocs-120.html
http://www.st.com/mcu/modules.php?name=mcu&file=familiesdocs&FAM=113
http://www.stmicroelectronics.com.cn/mcu/inchtml-pages-stm8l.html
http://www.stmicroelectronics.com.cn/mcu/inchtml-pages-stm8s.html

       
二,建立STVD+CXSTM8开发环境

1,双击sttoolset.exe,默认安装STVD和STVP到C盘的C:\Program Files\STMicroelectronics\st_toolset
将会在桌面产生ST Visual Develop和ST Visual Programmer的快捷方式;

2,解压COSMIC.rar到C盘的C:\Program Files\STMicroelectronics;

3,双击桌面的ST Visual Develop,打开STVD工具,在Tools->Options下的Toolset页面的Toolset中选择
STM8 cosmic,在Root path中选择C:\Program Files\STMicroelectronics\CXSTM8,然后应用,确定;

三,连接开发工具

1,把ST-LINK的SWIM电缆连接在ST-LINK和STM8S105S4-PKT开发板之间,共有4个信号:TVCC,SWIM,GND,RESET;

2,对STM8S105S4-PKT开发板加上9V的直流电源,把ST-LINK用USB线连接到PC的USB口上;

四,测试STM8S105S4-PKT演示工程

1,解压STM8S105S4-PKT演示代码.zip到PC上会得到一个Demo的目录;
2,用STVD工具的File->Open Workspace打开Demo\Touch Sensing\STM8S_EXAMPLE_FW\Project\STVD\Cosmic\example.stw;
3,用STVD工具的Debug instrument->Target Settings中的Debug Instrument Selection中选择Swim ST-LINK,应用,确定;
4,用STVD工具的Build->Rebuild All全部重新编译代码;
5,用STVD工具的Debug->Start Debugging下载代码到目标板上去;
6,然后可以使用单步执行,全速执行等命令,然后每按一次K3,K2,K1,相应的LD2,LD3,LD4就会相应的改变亮灭状态一次;
7,同样可以编译Demo\LED\Demo.stw和Demo\Music\Demo.stw等工程,查看LED流水灯和播放音乐。

五,用STVP+ST-LINK读写STM8

1,同样用ST-LINK的SWIM接口连接开发板和PC机,然后上电;
2,双击ST Visual Programmer打开STVP;
3,在STVP的Project->new 中建立一个新工程STM8S105S4-PKT.stp;
4,然后选择Hardware的ST-LINK,和Device的STM8S105x6确定;
5,用File->Open打开一个十六进制的HEX文件,然后用Program->All Tabs烧录进STM8去;
6,同样也可以用Read->All Tabs,来读出STM8中所有的目标码。

#44 Cortex M0/M3/M4/M7 » 9G-STM32 LwIP测试过程简介-缥缈九哥 » 2020-05-09 20:09:25

缥缈九哥
回复: 6

9G-STM32 LwIP测试过程简介

一,准备STM32 LwIP软件包

1,在http://www.st.com/mcu/devicedocs-STM32F107RC-110.html
    下载lwIP TCP/IP stack demonstration for STM32F107xx connectivity line microcontrollers软件包
    an3102.zip
    http://www.st.com/stonline/products/support/micro/files/an3102.zip
   
2,在http://www.st.com/mcu/devicedocs-STM32F107RC-110.html
    下载lwIP TCP/IP stack demonstration for STM32F107xx connectivity line microcontrollers文档
16620.pdf
http://www.st.com/stonline/products/literature/an/16620.pdf

3,有关STM32F107VC-PKT的PCB和SCH和测试代码见下面连接:

http://www.freescaleic.org/yuanxihua/blog/10-01/183297_155bc.html

二,建立STM32 LwIP开发工程

1,把an3102.zip解压到D:\works形成工程文件夹:D:\works\STM32F107_ETH_LwIP_V1.0.0 ;

2,进入到目录D:\works\STM32F107_ETH_LwIP_V1.0.0\Project\EWARMv5,双击Project.eww打开工程;

3,在EWARM中的Project->make 编译通过整个项目。

三,修改STM32 LwIP开发工程

1,打开Project->Options ,在Category中选择Debugger的setup驱动用J-Link/J-Trace,在J-Link/J-Trace
中选择connection的SWD接口;

2,对STM32F107VC-PKT开发板加上5V的直流电源,把J-LINK用USB线连接到PC的USB口上,执行Project->Download and Debug
下载代码到板子后,执行Debug->Go 。

四,修改STM32 LwIP开发源码

1,在D:\works\STM32F107_ETH_LwIP_V1.0.0\Project\src\main.c 的53行后添加如下代码:

   /* Output a message on Hyperterminal using printf function */
   printf("\n\r\n\r\n\r\n\r");
   printf("*** STM32F107VC-PKT V1.0 Build by yuanxihua@21cn.com on ("__DATE__ " - " __TIME__ ")\n\r");
   printf("*** STM32F107VC-PKT V1.0 Rebooting ...\n\r");

2,在D:\works\STM32F107_ETH_LwIP_V1.0.0\Project\src\stm32f107.c 的包含头文件中添加:
   #include "stdio.h"
 
在第30行选择用MII模式:
#define MII_MODE          /* MII mode for STM3210C-EVAL Board (MB784) (check jumpers setting) */
//#define RMII_MODE       /* RMII mode for STM3210C-EVAL Board (MB784) (check jumpers setting) */

在54行后添加:
USART_InitTypeDef USART_InitStructure;

在125行后添加:
 
   /* Configure the com port */
   /* USARTx configuration ------------------------------------------------------*/
   /* USARTx configured as follow:
         - BaudRate = 115200 baud
         - Word Length = 8 Bits
         - One Stop Bit
         - No parity
         - Hardware flow control disabled (RTS and CTS signals)
         - Receive and transmit enabled
   */
   USART_InitStructure.USART_BaudRate = 115200;
   USART_InitStructure.USART_WordLength = USART_WordLength_8b;
   USART_InitStructure.USART_StopBits = USART_StopBits_1;
   USART_InitStructure.USART_Parity = USART_Parity_No ;
   USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
   USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

   STM_EVAL_COMInit(COM1, &USART_InitStructure);
}

/**
   * @brief  Retargets the C library printf function to the USART.
   * @param  None
   * @retval : None
   */
int fputc(int ch, FILE *f)
{
   /* Write a character to the USART */
   USART_SendData(USART2, (uint8_t) ch);

   /* Loop until the end of transmission */
   while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET)
   {
   }

   return ch;
}
/**
   * @brief  Get a key from the HyperTerminal
   * @param  None
   * @retval : The Key Pressed
   */
int fgetc(FILE *f)
{
  /* Waiting for user input */
  while ( USART_GetFlagStatus(USART2, USART_FLAG_RXNE) == RESET);
  return (uint8_t)USART2->DR;

在341-344行修改为:
   /* ADC Channel10 config --------------------------------------------------------*/
   /* Relative to STM32F107VC-PKT Board   */
   /* Configure PC.00 (ADC Channel10) as analog input -------------------------*/
   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;

在375-376行修改为:
/* ADC1 regular channel10 configuration */
ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_13Cycles5);

3,在D:\works\STM32F107_ETH_LwIP_V1.0.0\Project\src\netconf.c 中的119-121行和316-318行把
IP地址都修改如下:
   IP4_ADDR(&ipaddr, 192, 168, 1, 8);
   IP4_ADDR(&netmask, 255, 255, 255, 0);
   IP4_ADDR(&gw, 192, 168, 1, 1);

4,在D:\works\STM32F107_ETH_LwIP_V1.0.0\Utilities\lwip-1.3.1\port\lwipopts.h中把
#define LWIP_DHCP               1
修改成:
#define LWIP_DHCP               0

5,在D:\works\STM32F107_ETH_LwIP_V1.0.0\Utilities\STM32_EVAL\STM3210C_EVAL\stm3210c_eval.h中把
#define LED1_GPIO_PIN               GPIO_Pin_7
修改成:
#define LED1_GPIO_PIN               GPIO_Pin_13

#define LED2_GPIO_PIN               GPIO_Pin_13
修改成:
#define LED2_GPIO_PIN               GPIO_Pin_14

#define LED3_GPIO_PIN               GPIO_Pin_3
修改成:
#define LED3_GPIO_PIN               GPIO_Pin_15


#define COMn                        1
修改成
#define COMn                        2


6,同样执行Project->Download and Debug 下载代码到板子后,执行Debug->Go 可以全速仿真运行。

五,演示STM32 LwIP开发工程

1,用交叉网线连接STM32F107VC-PKT到PC的网口,用交叉串口线连接RS232到PC的串口中,再对板子用5V上电
复位启动工作;
2,可以在串口终端上用115200 8N1的格式看到:
*** STM32F107VC-PKT V1.0 Build by yuanxihua@21cn.com on (Jan 12 2010 - 12:43:08)
*** STM32F107VC-PKT V1.0 Rebooting ...
3,在PC的IE浏览器中输入:http://192.168.1.8/ 回车刷新可以访问到板子,看到Home page主页:
STM32F107 Webserver Demo
Based on the lwIP TCP/IP stack
4,点击Led control从Home page切换LED控制,任意勾上或者去掉LED1-3,再按SEND,可以看到板子的LED相应的
被控制亮或者灭;
5,点击ADC status bar从Led control页面切换到ADC采集,旋转板子上的RV1,可以看到STM32F107 ADC status bar
上绿色的滚动条被ADC的输入电压控制增减;
6,在SecureCRT 5.1终端中可以以telnet协议访问192.168.1.8,端口就是23,连接上了会显示:
Hello. What is your name? ,输入字符串YUANXIHUA,马上会回复Hello YUANXIHUA

#45 Cortex M0/M3/M4/M7 » 9G-LM3S8 MDK-ARM使用过程简介--缥缈九哥 » 2020-05-09 20:08:46

缥缈九哥
回复: 0

9G-LM3S8 MDK-ARM使用过程简介

一,准备MDK-ARM+LM3S8软件包

1,在http://www.mcu123.com/news/Soft/embsof/arm/201001/516.html
    下载RealView MDK-ARM 4.03a(MDK-ARM V4.03a,MDK4.03a)
mdk403a_mcu123.rar
ftp://www.mcu123.com/%D2%D1%D5%FB%C0%ED%C4%BF%C2%BC/%BF%AA%B7%A2%B9%A4%BE%DF%C8%ED%BC%FE/ARM/mdk403a_mcu123.rar
(自己查找破解文件)

2,在http://www.luminarymicro.com/products/ekk-lm3s8962_can_ethernet_evaluation_kit.html 上
在Manuals and Schematics中的Quickstart Keil Tools-1.8 (Evaluation Kit Quickstart Keil Tools)
点击download注册下载Quickstart-Eval-Kit-Keil.pdf

在Manuals and Schematics中的EK-LM3S8962-08 (Stellaris LM3S8962 Evaluation Board User's Manual)
点击download注册下载8962_EvalBoard.pdf

在Manuals and Schematics中的RMF-EK-LM3S8962-1.4 (LM3S8962 Evaluation Kit Readme First)
点击download注册下载READMEFirst-LM3S8962-Eval-Kit.pdf

在Software Updates中的EKK-LM3S8962-CD-534 (LM3S8962 Evaluation Kit for Keil CD)
点击download注册下载EKK-LM3S8962-CD-534.zip

在Software Updates中的SW-EK-LM3S8962-5570 (EK-LM3S8962 Firmware Development Package)
点击download注册下载SW-EK-LM3S8962-5570.exe

3,在http://www.luminarymicro.com/products/software_updates.html 上
选择StellarisWare中的SW-EK-LM3S8962-5570 (EK-LM3S8962 Firmware Development Package)
点击download注册下载SW-EK-LM3S8962-5570.exe

选择Utilities中的LMFlashProgrammer-923 (GUI and command line flash programmere)
点击download注册下载LMFlashProgrammer_923.zip

选择Utilities中的Serial Flash Loader-00 (Serial Flash Loader)
点击download下载Serial Flash Loader.zip

选择Utilities中的LMIDK-AGDI-33 (Keil debug interface DLL for Stellaris ICDI)
点击download注册下载lmidk-agdi-b33.zip

选择Misc中的Stellaris FTDI Driver-2.06.00 (Stellaris FTDI driver)
点击download下载Stellaris_FTDI-2_06_00.zip

4,其它软件文档的下载地址如下:
http://www.luminarymicro.com/products/software_updates.html

       
二,建立MDK+LM3S8开发环境

1,双击MDK403a.exe自行安装MDK-ARM 4.03a,
将会在桌面产生Keil uVision4的快捷方式;

2,双击SW-EK-LM3S8962-5570.exe将软件安装到C盘的c:\StellarisWare;

3,双击LMFlashProgrammer_923.zip,运行里面的LMFlashProgrammer.msi安装FlashProgrammer到默认C盘,
将会在电脑桌面生成LM Flash Programmer的快捷方式;

三,连接开发工具

1,把EK-LM3S8962开发板用USB电缆连接到电脑上,将会发现找到新硬件Stellaris Development Board;

2,手动安装驱动程序时指向Stellaris_FTDI-2_06_00.zip的解压后的文件夹,安装Stellaris Development Board驱动;

3,再次出现新硬件Stellaris Virtual COM Port时,再指向刚才的目录即可安装相关驱动。

四,测试SW-EK-LM3S8962-5570.exe演示工程

1,用MDK打开C:\StellarisWare\boards\ek-lm3s8962\ek-lm3s8962.mpw工程;
2,在MDK的Project工程窗口的graphics上右击Set as Active Project;
3,在MDK工程窗口菜单中选择Flash->Download命令编译下载目标码;
4,复位LM3S8962的开发板,也可以编译下载后用Debug->Start命令启动调试后全速运行;
5,便可在LM3S8962的开发板的OLED上看到luminarymicro的LOGO;
6,也可以选择激活Project工程窗口其它它工程来运行;
7,如qs_ek-lm3s8962就是显示了TI和KEIL的LOGO后一个小迷宫游戏。

五,用LM Flash Programmer读写LM3S8962

1,同样用USB电缆连接开发板和PC机;
2,双击桌面LM Flash Programmer打开Programmer;
3,在Configureation的Quick Set中选择LM3S8962...;
4,然后在Flash Utilities的Upload...中指定一个BIN文件;
5,选择整块FLASH然后Upload便可以读出LM3S8962中的目标码;
6,同样也可以把目标码写入LM3S8962。

#46 Cortex M0/M3/M4/M7 » 9G-LM3S8 EWARM使用过程简介--缥缈九哥 » 2020-05-09 20:08:06

缥缈九哥
回复: 2

9G-LM3S8 EWARM使用过程简介

一,准备EWARM+LM3S8软件包

1,在http://www.mcu123.com/news/Soft/embsof/arm/201001/514.html
    下载IAR Embedded Workbench for ARM version 5.41 (2010.1.5更新)
CD-EWARM-5411-1760_mcu123.zip
http://esoft.mcu123.com/MCU123_temp_20100103@/ARM/CD-EWARM-5411-1760_mcu123.zip
(自己查找破解文件)

2,在http://www.luminarymicro.com/products/eki-lm3s8962_can_ethernet_evaluation_kit.html
在Manuals and Schematics中的Quickstart IAR Tools-1.7 (Evaluation Kit Quickstart IAR Tools)
点击download注册下载Quickstart-Eval-Kit-IAR.pdf

在Manuals and Schematics中的EK-LM3S8962-08 (Stellaris LM3S8962 Evaluation Board User's Manual)
点击download注册下载8962_EvalBoard.pdf

在Manuals and Schematics中的RMF-EK-LM3S8962-1.4 (LM3S8962 Evaluation Kit Readme First)
点击download注册下载READMEFirst-LM3S8962-Eval-Kit.pdf

在Software Updates中的EKI-LM3S8962-CD-534 (LM3S8962 Evaluation Kit for IAR CD)
点击download注册下载EKI-LM3S8962-CD-534.zip

在Software Updates中的SW-EK-LM3S8962-5570 (EK-LM3S8962 Firmware Development Package)
点击download注册下载SW-EK-LM3S8962-5570.exe

3,在http://www.luminarymicro.com/products/software_updates.html 上
选择StellarisWare中的SW-EK-LM3S8962-5570 (EK-LM3S8962 Firmware Development Package)
点击download注册下载SW-EK-LM3S8962-5570.exe

选择Utilities中的LMFlashProgrammer-923 (GUI and command line flash programmere)
点击download注册下载LMFlashProgrammer_923.zip

选择Utilities中的Serial Flash Loader-00 (Serial Flash Loader)
点击download下载Serial Flash Loader.zip

选择Utilities中的LMIDK-AGDI-33 (Keil debug interface DLL for Stellaris ICDI)
点击download注册下载lmidk-agdi-b33.zip

选择Misc中的Stellaris FTDI Driver-2.06.00 (Stellaris FTDI driver)
点击download下载Stellaris_FTDI-2_06_00.zip

4,其它文档的下载地址如下:
http://www.luminarymicro.com/products/software_updates.html

       
二,建立EWARM+LM3S8开发环境

1,双击CD-EWARM-5411-1760.zip,运行里面的autorun.exe默认安装IAR EWARM到C盘,
将会在电脑启动菜单中产生IAR Embedded Workbench的快捷方式;

2,双击SW-EK-LM3S8962-5570.exe将软件安装到C盘的c:\StellarisWare;

3,双击LMFlashProgrammer_923.zip,运行里面的LMFlashProgrammer.msi安装FlashProgrammer到默认C盘,
将会在电脑桌面生成LM Flash Programmer的快捷方式;

三,连接开发工具

1,把EK-LM3S8962开发板用USB电缆连接到电脑上,将会发现找到新硬件Stellaris Development Board;

2,手动安装驱动程序时指向Stellaris_FTDI-2_06_00.zip的解压后的文件夹,安装Stellaris Development Board驱动;

3,再次出现新硬件Stellaris Virtual COM Port时,再指向刚才的目录即可安装相关驱动。

四,测试SW-EK-LM3S8962-5570.exe演示工程

1,双击C:\StellarisWare\boards\ek-lm3s8962\ek-lm3s8962.eww用EWARM打开工程;
2,在EWARM工程窗口的Workspace中选择graphics-Debug;
3,在EWARM工程窗口菜单中选择Project->Download and Debug命令;
4,在EWARM的高度窗口中选择Debug->Go全速运行;
5,便可在LM3S8962的开发板的OLED上看到luminarymicro的LOGO;
6,也可以选择Workspace中选择其它工程来运行;
7,如qs_ek-lm3s8962-Debug就是显示了TI和IAR的LOGO后一个小迷宫游戏。

五,用LM Flash Programmer读写LM3S8962

1,同样用USB电缆连接开发板和PC机;
2,双击桌面LM Flash Programmer打开Programmer;
3,在Configureation的Quick Set中选择LM3S8962...;
4,然后在Flash Utilities的Upload...中指定一个BIN文件;
5,选择整块FLASH然后Upload便可以读出LM3S8962中的目标码;
6,同样也可以把目标码写入LM3S8962。

#47 VMWare/Linux/Ubuntu/Fedora/CentOS/U-BOOT » U-BOOT移植过程流水账--缥缈九哥 » 2020-05-09 20:07:10

缥缈九哥
回复: 0

U-BOOT移植过程流水账

1,修改MAKEFILE

增加开发板编译定义

at91sam9260ek_config : unconfig
@./mkconfig $(@:_config=) arm arm926ejs at91sam9260ek NULL at91sam926x

指定编译器

ifeq ($(ARCH),arm)
CROSS_COMPILE = /usr/local/arm/eldk-4.1/usr/bin/arm-linux-


2,修改MAKEALL

增加ARM9开发板支持列表

LIST_ARM9=" \
at91rm9200dk cmc_pu2      \
at91sam9260ek at91sam9261ek at91sam9263ek   \

3,\include\asm-arm\mach-types.h的修改

增加CPU型号定义

#define MACH_TYPE_AT91SAM9261EK        848
#define MACH_TYPE_PDNB3               1002
#define MACH_TYPE_AT91SAM9260EK       1099
#define MACH_TYPE_AT91SAM9263EK       1202


4,include\configs\at91sam9260ek.h

增加开发板定义头文件

at91sam9260ek.h

5,include\asm-arm\arch-at91sam926x\at91sam9260.h

增加CPU的寄存器定义头文件

at91sam9260.h

6,examples\Makefile

修改如此类
ELF = hello_world
编译错误

7,board\at91sam9260ek\

增加开发板定义文件夹
at91sam9260ek.c  config.mk dm9161a.c Makefile nand.c u-boot.lds


8,cpu\arm926ejs\at91sam926x\

增加CPU核的支持文件夹

config.mk ether.c interrupts.c lcd.c lcd_lut.h Makefile serial.c  spi.c usb_ohci.c usb_ohci.h

启动过程

1,\cpu\arm926ejs\start.S
A,在\board\at91sam9260ek\u-boot.lds 中定义程序入口标志为 ENTRY(_start) TEXT段首文件: cpu/arm926ejs/start.o (.text)
B,在\board\at91sam9260ek\config.mk  中定义程度执行地址为 TEXT_BASE = 0x23f00000
C, _start -> cpu_init_crit -> relocate -> stack_setup -> clear_bss -> start_armboot 先初始化系统,然后进入主循环
D,中断处理
2,\lib_arm\board.c
start_armboot() 先初始化系统,然后进入主循环

A, *init_sequence[] 初始化列表

cpu_init 在 \cpu\arm926ejs\cpu.c
board_init 在 \board\at91sam9260ek\at91sam9260ek.c
interrupt_init 在\cpu\arm926ejs\at91sam926x\interrupts.c
env_init 在\common\env_dataflash.c 或者 \common\env_nand.c
  (include\configs\at91sam9260ek.h 中CFG_ENV_IS_IN_DATAFLASH CFG_ENV_IS_IN_NAND 决定)
init_baudrate  在\lib_arm\board.c
serial_init 在\cpu\arm926ejs\at91sam926x\serial.c
console_init_f 在\common\console.c
display_banner 在\lib_arm\board.c
print_cpuinfo  在\cpu\arm926ejs\cpuinfo.c
checkboard 不启用
dram_init 在 \board\at91sam9260ek\at91sam9260ek.c
display_dram_config 在\lib_arm\board.c

B,外设初始化配置

flash_init NORFLASH初始化
display_flash_config NORFLASH信息显示
(include\configs\at91sam9260ek.h 中CFG_NO_FLASH 决定不用)

LCD VFD都不用 include\configs\at91sam9260ek.h 中CONFIG_VFD CONFIG_LCD 定义不用

mem_malloc_init 初始化malloc空间 在\lib_arm\board.c

nand_init 在\drivers\nand\nand.c

AT91F_DataflashInit 在\drivers\dataflash.c
dataflash_print_info  在\drivers\dataflash.c

env_relocate 在\common\env_common.c

getenv_IPaddr 在\net\net.c
getenv 在\common\cmd_nvedit.c

devices_init 在\common\devices.c
jumptable_init 在\common\exports.c
console_init_r 在\common\console.c
enable_interrupts 在\cpu\arm926ejs\interrupts.c
board_late_init  在\board\at91sam9260ek\at91sam9260ek.c
eth_initialize 在\net\eth.c

C,进入主循环

main_loop  在\common\main.c
 
3,\common\main.c

A,启动禁用 CONFIG_BOOTCOUNT_LIMIT,CONFIG_MODEM_SUPPORT,VFD_TEST_LOGO,CONFIG_VERSION_VARIABLE,CFG_HUSH_PARSER,
CONFIG_PREBOOT,CONFIG_AUTOBOOT_KEYED,CONFIG_BOOT_RETRY_TIME,CONFIG_MENUKEY,CONFIG_AMIGAONEG3SE,CONFIG_AMIGAONEG3SE

include\configs\at91sam9260ek.h 中没有定义

B,判断自启动延时
abortboot 在\common\main.c
parse_string_outer  在\common\hush.c

C,命令终端for (;;)

禁用 CONFIG_RESET_TO_RETRY CONFIG_AUTO_COMPLETE
在include\configs\at91sam9260ek.h 中没有定义

readline 在\common\main.c
run_command 在\common\main.c


添加过程

1,修改MAKEFILE

在\common\Makefile的 COBJS =
后面目标码协列表中添加新的目标码 cmd_xmodem.o xmodem.o

2,增加源文件

在\common\中增加源文件
xmodem.c cmd_xmodem.c

3,增加头文件

在\include\中增加头文件

xmodem.h

4,添加命令过程

A,核心处理函数
int do_xmodem(cmd_tbl_t *cmdtp,int flag,int argc, char *argv[])

B,命令定义模板
U_BOOT_CMD(
  rx,    3,    0,     do_xmodem,
"rx      - load binary file over serial line (xmodem)\n",
"[ off ] [ baud ]\n"
"    - load binary file over serial line"
" with offset 'off' and baudrate 'baud'\n"
);

C,命令模板定义

命令结构体
typedef struct cmd_tbl_s cmd_tbl_t

命令模板宏
#define U_BOOT_CMD(name,maxargs,rep,cmd,usage,help) \
cmd_tbl_t __u_boot_cmd_##name Struct_Section = {#name, maxargs, rep, cmd, usage, help}

在 \include\command.h

D,XMODEM协议核心

int xmodem_rx(char *dest)

#48 Cortex M0/M3/M4/M7 » 9G-CM0 新唐CM0+MDK-ARM入门开发过程简介-缥缈九哥 » 2020-05-09 20:06:05

缥缈九哥
回复: 0

9G-CM0 新唐CM0+MDK-ARM入门开发过程简介

一,准备MDK-ARM + 新唐CM0软件包

1,在http://www.mcu123.com/news/Soft/embsof/arm/201006/529.html
    下载RealView MDK-ARM 4.12 (MDK-ARM V4.12,MDK4.12)
mdk412_mcu123.rar
在http://www.mcu123.com/news/Soft/ShowSoftDown.asp?UrlID=3&SoftID=529上
右击“下载地址:”后的“下载”选择“目标另存为”下载文件到本地硬盘。
(自己查找破解文件“keygen.exe”)
http://esoft.mcu123.com/MCU123_temp_20100103@/arm/mdk412_mcu123.rar

2,在http://www.nuvoton.com/NuvotonMOSS/Community/ProductInfo.aspx?tp_GUID=403a9c50-52c2-4463-9057-2595190602c5 上
上下载 “NUC1xx Keil ICE driver (Build 3814) V1.01.zip”
NUC1xxKeilICEdriverBuild3814V101.zip
http://www.nuvoton.com/hq/enu/ProductAndSales/ProductLines/ConsumerElectronicsIC/ARMMicrocontroller/ARMCortexTMM0/Documents/NUC1xxKeilICEdriverBuild3814V101.zip
   
下载“NUC1xx Nu-Tiny-EVB and Nu-Link-Me Board user manual EN v1.0.pdf”文档
NUC1xxNuTinyEVBandNuLinkMeBoardusermanualENv10.pdf
http://www.nuvoton.com/hq/enu/ProductAndSales/ProductLines/ConsumerElectronicsIC/ARMMicrocontroller/ARMCortexTMM0/Documents/NUC1xxNuTinyEVBandNuLinkMeBoardusermanualENv10.pdf

下载“NUC1xx Nu-Link-Me_001 Board Schematic v1.0.pdf”文档
NUC1xxNuLinkMe_001BoardSchematicv10.pdf
http://www.nuvoton.com/hq/enu/ProductAndSales/ProductLines/ConsumerElectronicsIC/ARMMicrocontroller/ARMCortexTMM0/Documents/NUC1xxNuLinkMe_001BoardSchematicv10.pdf

下载“NUC1xx Nu-Tiny-EVB_001 Board Schemetic v1.0.pdf”文档
NUC1xxNuTinyEVB_001BoardSchemeticv10.pdf
http://www.nuvoton.com/hq/enu/ProductAndSales/ProductLines/ConsumerElectronicsIC/ARMMicrocontroller/ARMCortexTMM0/Documents/NUC1xxNuTinyEVB_001BoardSchemeticv10.pdf

3,在http://www.nuvoton.com/NuvotonMOSS/Community/ProductInfo.aspx?tp_GUID=7052964b-b71b-46b7-91b2-221afeddd575上
上下载 “NUC1xxBSP_v1.1.1.zip”
NUC1xxBSP_v111.zip
http://www.nuvoton.com/NuvotonMOSS/Community/ProductInfo.aspx?tp_GUID=38a57efd-e9f8-4809-a585-21e62f8b6041

4,新唐官方资料网址
新唐CM0官方资料主页
http://www.nuvoton.com/hq/chs/Pages/default.aspx
新唐CM0主页资料入口
ARM单片机 -> ARM Cortex?-M0 单片机 NuMicro? 家族
新唐CM0主页资料网址
http://www.nuvoton.com/NuvotonMOSS/Community/ProductInfo.aspx?tp_GUID=30cfcae5-0f93-414d-a8df-b3bac8b932a2
新唐CM0在线选型工具
http://www.nuvoton.com/hq/enu/ProductAndSales/ProductLines/ConsumerElectronicsIC/ARMMicrocontroller/ARMCortexTMM0/Pages/SelectGuide.aspx
新唐CM0在线培训教程
http://www.nuvoton.com/hq/enu/ProductAndSales/ProductLines/ConsumerElectronicsIC/ARMMicrocontroller/ARMCortexTMM0/Pages/OnLineTraining.aspx

二,建立CM0的MDK-ARM+Nu-LINK开发环境

1,双击“mdk412_mcu123.rar”运行里面的“MDK412.exe”,一路的“NEXT”再“NEXT”,最后就会安装MDK-ARM 4.12到电脑上,将会在桌面产生Keil uVision4的快捷方式;

2,双击“keygen.exe”,把“uVision4”的“File->License Management”菜单里面的“CID”复制到keygen里面的CID框中,选择“TARGET”为“ARM”后点击“Generate”,把
产生的序列号复制到前面“uVision4”的窗口中的“LIC”框中,点击“ADD LIC”便会解除编译限制;

3,双击“NUC1xxKeilICEdriverBuild3814V101.zip ”运行里面的“Nu-Link_Driver.EXE”,便会在KEIL目录中安装上相关的“Nu-LINK”的驱动。

三,建立CM0的MDK-ARM基本工程

1,在电脑开始菜单中打开“Keil uVision4”,在“uVision4”的IDE菜单中选择“Project”->“New uVision Project”创建一个新工程,在“Create New Project”选择存储目录
到D:\works\9G-CM0\nuc140\project下面,工程名叫“nuc140.uvproj”;

2,接着在“select a CPU Data Base File”菜单中选择“NUVOTON NUC1XX Devices”点击“OK”,选择“Nuvoton”公司下面的“NUC140VE3AN”点击“OK”后确认复制启动代码“startup_NUC1xx.s”和
加入到工程项目中,即可产生一个空工程,再点击全部保存项目,会D:\works\9G-CM0\nuc140\project目录中发现“nuc140.uvproj”和“nuc140.uvopt”,“startup_NUC1xx.s”等文件;

3,在“D:\works\9G-CM0\nuc140”下建立文件夹“include”,“driver”,“library”,“source”,等子目录,解压“NUC1xxBSP_v111.zip”,把里面的目录“NUC1xxBSP”解压到“library”里面,在D:\works\9G-CM0\nuc140\project
下建立子目录“obj”和“lst”;

4,在“uVision4”的IDE菜单中选择“Project”->“Manage”->“Components,Environment,Books”打开“Components,Environment,Books”页面里的“Project Components”,
双击“Target1”改名为“NUC140”,双击“Source Group 1”改名为“boot”再添加“lib”“drv”“src”“inc”等目录后确定。

5,在“uVision4”的IDE菜单中选择“File”->“New”后选择“File”->“Save”把新建立的文件保存到D:\works\9G-CM0\nuc140\source,文件名为“main.c”,右击项目窗口中的“src”选择“Add Files
to Group 'src'”并在“main.c”中填入下面内容:
  #include <NUC1xx.H>                            /* NUC1xx definitions                 */
  void SystemInit(void){}
  void GPIO_Init(void){ NUC_GPIOC->PMD   = 0x00005555;}     /* LEDs on PORT C defined as Output   */
  int main(void)
  {
   int i;
 
   GPIO_Init();
   while(1)
   {
    for(i=0;i<1000000;i++);  NUC_GPIOC->DOUT &= 0xFFFFFF00; /* switch on LEDs                    */
    for(i=0;i<1000000;i++);  NUC_GPIOC->DOUT |= 0x000000FF; /* switch off LEDs                    */
   }
  }
 
三,配置CM0的MDK-ARM基本工程

1,在“uVision4”的IDE菜单中选择“Project”->“Opitions for Target ‘NUC140’”,在“Output”页面勾选“Create HEX File”,并在“Select Folder Objects”指定目录到“D:\works\9G-CM0\nuc140\project\obj”,
后点击“OK”,同样在“Listing”中在“Select Folder Listings”指定目录到“D:\works\9G-CM0\nuc140\project\lst”;

2,在“Opitions for Target ‘NUC140’”的“Debug”页面选择用硬件仿真器“Nu-Link Debugger”勾选“Run to main{}”,在“Utilities”页面选择“Use Target Driver for Flash Programming”用
“Nu-Link Debugger”勾选上“Update Target before Debugging”后在“Setting”里面的“Configure”,确保用内置22M晶体,和从“APROM”启动及低压检测电压值等配置选项后点击“OK”再“OK”退出;

3,在“Opitions for Target ‘NUC140’”的“C/C++”页面的“Include Paths”中填入“C:\Keil\ARM\INC\Nuvoton\NUC1xx”

四,调试CM0的MDK-ARM基本工程

1,点击在“uVision4”的IDE菜单中选择“Flash”->“Download”便会自己编译代码生成HEX文件并下载到目标板子中;

2,点击在“uVision4”的IDE菜单中选择“Debug”->“Start/Stop Debug session”进入调试状态,然后选择“Debug”->“Run”,全速运行,可以看到IO口上的LED在闪烁。

四,建立CM0的MDK-ARM高级工程
(待续)

#49 Cortex M0/M3/M4/M7 » 9G-CM0 新唐CM0+EWARM入门开发过程简介--缥缈九哥 » 2020-05-09 20:05:08

缥缈九哥
回复: 0

9G-CM0 新唐CM0+EWARM入门开发过程简介

一,准备EWARM + 新唐CM0软件包

1,在http://www.mcu123.net/bbs/viewthread.php?tid=16064&highlight=CD-EWARM-5501-1908 上
下载 IAR Embedded Workbench for ARM version 5.50 软件
CD-EWARM-5501-1908_mcu123.zip
    ftp://mcu123:mcu123@mcu123.com/已整理目录/开发工具软件/ARM/CD-EWARM-5501-1908_mcu123.zip
    相关文件“IAR_EWARM5.4和谐文件.rar ”可以在GOOGLE上搜索到
    http://bbs.mcu123.net/bbs/thread-15164-1-1.html
    并下载:
    IAR_EWARM5[1].4和谐文件.rar   

2,在http://www.nuvoton.com/NuvotonMOSS/Community/ProductInfo.aspx?tp_GUID=403a9c50-52c2-4463-9057-2595190602c5 上
下载 “NuMicro IAR Embedded Workbench? driver (Build 4033) V1.02.zip”
NuMicro IAR Embedded Workbench driver  (Build 4033) V1.02.zip
http://www.nuvoton.com/hq/enu/ProductAndSales/ProductLines/IndustrialIC/ARMMicrocontroller/ARMCortexTMM0/Documents/NuMicro%20IAR%20Embedded%20Workbench%20driver%20%20(Build%204033)%20V1.02.zip
     
下载“NUC1xx Nu-Tiny-EVB_001 Board Schemetic v1.0.pdf”文档
NUC1xxNuTinyEVB_001BoardSchemeticv10.pdf
http://www.nuvoton.com/hq/enu/ProductAndSales/ProductLines/IndustrialIC/ARMMicrocontroller/ARMCortexTMM0/Documents/NUC1xxNuTinyEVB_001BoardSchemeticv10.pdf

下载“NUC1xx Nu-Tiny-EVB and Nu-Link-Me Board user manual EN  v1.0.pdf”文档
NUC1xxNuTinyEVBandNuLinkMeBoardusermanualENv10.pdf
http://www.nuvoton.com/hq/enu/ProductAndSales/ProductLines/IndustrialIC/ARMMicrocontroller/ARMCortexTMM0/Documents/NUC1xxNuTinyEVBandNuLinkMeBoardusermanualENv10.pdf

下载“NUC1xx Nu-Link-Me_001 Board Schematic v1.0.pdf”文档
NUC1xxNuLinkMe_001BoardSchematicv10.pdf
http://www.nuvoton.com/hq/enu/ProductAndSales/ProductLines/IndustrialIC/ARMMicrocontroller/ARMCortexTMM0/Documents/NUC1xxNuLinkMe_001BoardSchematicv10.pdf

3,在http://www.nuvoton.com/NuvotonMOSS/Community/ProductInfo.aspx?tp_GUID=7052964b-b71b-46b7-91b2-221afeddd575上
上下载 “NUC1xxBSP_v1.1.2.zip”
NUC1xxBSP_v1.1.2.zip
http://www.nuvoton.com/hq/enu/ProductAndSales/ProductLines/IndustrialIC/ARMMicrocontroller/ARMCortexTMM0/Documents/NUC1xxBSP_v1.1.2.zip

4,新唐官方资料网址
新唐CM0官方资料主页
http://www.nuvoton.com/hq/chs/Pages/default.aspx
新唐CM0主页资料入口
ARM单片机 -> ARM Cortex?-M0 单片机 NuMicro? 家族
新唐CM0主页资料网址
http://www.nuvoton.com/NuvotonMOSS/Community/ProductInfo.aspx?tp_GUID=5cc43799-121d-42c9-9ac0-3b4a6cbdb7c3
新唐CM0在线选型工具
http://www.nuvoton.com/hq/enu/ProductAndSales/ProductLines/IndustrialIC/ARMMicrocontroller/ARMCortexTMM0/Pages/SelectGuide.aspx
新唐CM0在线培训教程
http://www.nuvoton.com/hq/enu/ProductAndSales/ProductLines/IndustrialIC/ARMMicrocontroller/ARMCortexTMM0/Pages/onlineEtraining.aspx

5,在http://www.segger.com/cms/jlink-software.html 上
    下载Software and documentation pack V4.14g软件
Setup_JLinkARM_V414g.zip
http://www.segger.com/cms/admin/uploads/userfiles/file/J-Link/Setup_JLinkARM_V414g.zip
   
二,建立CM0的EWARM+Nu-LINK开发环境

1,双击“IAR_EWARM5[1].4和谐文件.rar”,运行里面的“EWARM_FULL_ARM540.exe”,选择“Product”中的“Embedded Workbench For ARM v5.40”,然后点击“Generate”
把产生的“License key”“License number”密码和序列号记录下来;

2,双击“CD-EWARM-5501-1908_mcu123.zip”运行里面的“autorun.exe”,在“Welcome to IAR Systems”中选择“Install IAR Embedded Workbench”,按常规的软件安装方式
把“IAR Embedded Workbench For ARM”安装到电脑上;

3,双击“NuMicro IAR Embedded Workbench driver  (Build 4033) V1.02.zip”运行里面的“Nu-Link_IAR_Driver 1.02.exe”,便会在“C:\Program Files\Nuvoton Tools\Nu-Link_IAR”
目录中安装上相关的“Nu-LINK”的驱动。

4,双击“Setup_JLinkARM_V414g.zip”运行里面的“Setup_JLinkARM_V414g.exe”,便会在“C:\Program Files\SEGGER\JLinkARM_V414g”
目录中安装上相关的“J-LINK”的驱动。

三,建立CM0的EWARM基本工程

1,在电脑开始菜单中打开“IAR Embedded Workbench IDE”,在“EWARM”的IDE菜单中选择“Project”->“Create New Project”创建一个新工程,在“Create New Project”选择“OK”存储目录
到D:\works\9G-CM0\nuc140\project\iar下面,工程名叫“nuc140.ewp”,点击“OK”完成,点击“File”下的“Save Workspace”保存工作空间到目录中的“nuc140.eww”;

2,在“D:\works\9G-CM0\nuc140”下建立文件夹“include”,“driver”,“library”,“source”,等子目录,在“D:\works\9G-CM0\nuc140\project\iar下建立子目录“config”,并把
“NUC1xxBSP_v1.1.2.zip”解压到“D:\works\9G-CM0\nuc140\library”目录;

3,在“EWARM”的IDE菜单中选择“Project”->“Options”中的“General Options”的“Target”中的“Device”中选择“Nuvoton NUC140xE”,在“Linker”菜单中选择“Linker configuration file”里选择
“override default”并填上“$PROJ_DIR$\config\NUC140_Flash.icf”;

4,在“Options for node 'nuc140'”的“Category:”中选择上“Debugger”,在“Setup”->“Driver”中选择“Third-Party Driver”,然后在“Third-Party Driver”选择驱动到
“C:\Program Files\Nuvoton Tools\Nu-Link_IAR\Nu-Link_IAR.dll”;

5,在“Debugger”的“Download”勾选择“Use flash loader”和“override default .board file”并填入“$TOOLKIT_DIR$\config\flashloader\Nuvoton\FlashNUC1xxxE.board”,把
“D:\works\9G-CM0\nuc140\library\NUC1xxBSP\NuvotonPlatform_IAR\Sample\Driver\Smpl_DrvGPIO”下的“Smpl_DrvGPIO.icf”复制到“D:\works\9G-CM0\nuc140\project\iar\config”
并改名为“NUC140_Flash.icf”;

6,在“IAR Embedded Workbench IDE”的“Workspace”下的“Files”中右击选择“Add”->“Add Group”并填入“BOOT”,另外同样建立“DRV”,“SRC”,“INC”“LIB”等目录,然后在“BOOT”上右击
选择“Add”->“Add Files” 然后选择“D:\works\9G-CM0\nuc140\library\NUC1xxBSP\CMSIS\CM0\startup\iar”下的“ startup_NUCxxx_iar.s”;

7,在“D:\works\9G-CM0\nuc140\source”中建立“main.c”,然后添加到工程的“SRC”中,并在“main.c”中填入下面内容:
  #include <Nuvoton\ionuc140.h>

  void SystemInit(void){}
 
  void GPIO_Init(void){ GPIOC_PMD = 0x55555555;GPIOA_PMD = 0x55555555;}     /* LEDs on PORT C defined as Output   */
 
  int main(void)
  {
   int i;
   
   GPIO_Init();
   while(1)
   {
    for(i=0;i<3000000;i++); 
          GPIOC_DOUT &= 0x00000000; /* switch on LEDs                    */
    GPIOA_DOUT &= 0x00000000;
    for(i=0;i<3000000;i++); 
          GPIOC_DOUT |= 0xFFFFFFFF; /* switch off LEDs                    */
    GPIOA_DOUT |= 0xFFFFFFFF;
   }
  }
 
8,在“Debugger”的“Download”勾选择“Use flash loader”和“override default .board file”并填入“$TOOLKIT_DIR$\config\flashloader\Nuvoton\LDROMNUC1xx.board”,可以把
相应的程序烧进LDROM区;

9,在“EWARM”的IDE菜单中选择“Nu-Link”->“ICP Programming Tool”中,可以不擦除整片FLASH改变配置位从APPROM区切换到LDROM区,
FLASH的1能修改成0;

四,调试CM0的EWARM基本工程

1,在“EWARM”的IDE菜单中选择“Project”->“Options”中“Category:”中选择上“Debugger”,在“Setup”->“Driver”中选择“J-Link/J-Trace”;

2,在“Debugger”的“Download”勾选择“Use flash loader”和“override default .board file”并填入“$TOOLKIT_DIR$\config\flashloader\Nuvoton\LDROMNUC1xx.board”,可以把
相应的程序烧进LDROM区;

(待续)

#50 Cortex M0/M3/M4/M7 » 基于IAR EWARM开发新唐M0的CONFIG修改及NU-LINK驱动与ISP要点--缥缈九哥 » 2020-05-09 20:04:26

缥缈九哥
回复: 0

基于IAR EWARM开发新唐M0的CONFIG修改及NU-LINK驱动
1,把下面的内容保存成文件“nuc1xx_APROM.board”:
<?xml version="1.0" encoding="iso-8859-1"?>
<flash_board>
  <pass>
    <loader>$TOOLKIT_DIR$\config\flashloader\Nuvoton\FlashNUC1xxxE.flash</loader>
    <args>--config</args>
  </pass>
</flash_board>
2,把下面的内容保存成文件“nuc1xx_LDROM.board”:
<?xml version="1.0" encoding="iso-8859-1"?>
<flash_board>
  <pass>
    <loader>$TOOLKIT_DIR$\config\flashloader\Nuvoton\LDROMNUC1xx.flash</loader>
    <abs_offset>0x100000</abs_offset>
    <args>--config
0xFFFFFF7F
0x0001F800</args>
  </pass>
</flash_board>
注:其中参数:     <args>--config
0xFFFFFF7F
0x0001F800</args>
就是新唐M0的配置区的CONFIG0,1 的值,严格根据你的需要的配置去修改。
3,然后在IAR EWARM的项目工程的Options->Debugger->Dwnload里勾选上Use flash loader及Override default .boadr file。
然后下面填上路径:
$PROJ_DIR$\nuc1xx_LDROM.board
或者
$PROJ_DIR$\nuc1xx_APROM.board
4,双击NuMicro IAR Embedded Workbench driver (Build 4228) V1.03.ZIP把
NU-LINK的驱动默认安装到电脑上,然后IAR EWARM的项目工程的Options->Debugger的驱动
驱动用Third-Party Driver的,再指定到NU-LINK的DLL路径:
C:\Program Files\Nuvoton Tools\Nu-Link_IAR\Nu-Link_IAR.dll
5,新唐M0的ISP的要点:
1,CPU的LDROM中要烧有ISP_LD_NUC100series.bin(针对NUC1XX)或者ISP_LD_M051series.bin(针对M05X);
2,CPU的CONFIG0要配置从LDROM启动,甚至要配置外部12M晶体(用USB下载做ISP);
3,CPU的UART0或者USB(NUC120,140)上要有线正确连接到PC上;
4,CPU的上电复位时,NUC1XX是INT1(PB15)或者M05X是INT0(P3.2)要接地,否则跳进APROM;
5,CPU进入了ISP后再用NuMicro ISP Writer V1.10.exe去连接CPU(选择对的COM口或者USB口)
6,CPU的ISP连接后不能操作LDROM,但可以在重新复位前多次操作APROM和CONFIG和DATAFLASH;
7,CPU的ISP软件PC端NuMicro ISP Writer V1.10.exe的同一目录要有config.ini文件。

#51 Cortex M0/M3/M4/M7 » 启动新唐M0的semihost半主机调试--缥缈九哥 » 2020-05-09 20:03:33

缥缈九哥
回复: 0

启动新唐M0的semihost半主机调试:
利用NUC100SERIESBSP_CMSIS_V1.03.002建立的工程。
1,针对startup_NUC1xx.s文件的修改
A,第010行改为:SEMIHOSTED       SETL    {TRUE} ;SEMIHOSTED       SETL    {FALSE}
B,第256行改为:;yuanxihua@21cn.com                ENTRY
2,针对 retarget.c文件的修改
A,第021行改为:#define DEBUG_ENABLE_SEMIHOST   /* To enable semihosted. !!!The SEMIHOSTED of startup_NUC1xx.s must be {TRUE} */
3,在MDK的NU-LINK的Debug模式中,打开View->Serial Windows-> UART #1即可利用如下调试信息:
printf("*** 9G-NUC122 V1.00 Build by yuanxihua@21cn.com on ("__DATE__ " - " __TIME__ ")\n\r");
printf("*** 9G-NUC122 V1.00 Rebooting ...\n\r\n\r");
打印到上面的虚拟串口。

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0203ic/Bgbjjgij.html

8.1.1. 什么是半主机?

半主机是用于 ARM 目标的一种机制,可将来自应用程序代码的输入/输出请求传送至运行调试器的主机。 例如,使用此机制可以启用 C 库中的函数,如
printf()

scanf()
,来使用主机的屏幕和键盘,而不是在目标系统上配备屏幕和键盘。

这种机制很有用,因为开发时使用的硬件通常没有最终系统的所有输入和输出设备。 半主机可让主机来提供这些设备。

半主机是通过一组定义好的软件指令(如 SVC)来实现的,这些指令通过程序控制生成异常。 应用程序调用相应的半主机调用,然后调试代理处理该异常。 调试代理提供与主机之间的必需通信。

半主机接口对 ARM 公司提供的所有调试代理都是通用的。 在无需移植的情况下使用 RealView ARMulator? ISS、指令集系统模型 (ISSM)、实时系统模型 (RTSM)、RealView ICE 或 RealMonitor 时,会执行半主机操作,请参阅Figure 8.1。

在很多情况下,半主机由库函数内的代码调用。 应用程序还可以直接调用半主机操作。 有关 ARM C 库中的半主机支持的详细信息,请参阅《库和浮点支持指南》中的第 2 章 C 和 C++ 库。

#52 Cortex M0/M3/M4/M7 » 9G-NUC140 新唐CM0+EWARM入门开发过程简介--缥缈九哥 » 2020-05-09 20:02:53

缥缈九哥
回复: 0

9G-NUC140 新唐CM0+EWARM入门开发过程简介

一,准备EWARM + 新唐CM0软件包

1,在http://www.mcu123.com/news/Soft/ShowSoftDown.asp?UrlID=1&SoftID=535 上
下载 IAR Embedded Workbench for ARM v6.20 FULL CD-EWARM-6201-2590 软件
CD-EWARM-6201-2590_mcu123.zip
    ftp://mcu123:mcu123@mcu123.com/已整理目录/开发工具软件/ARM/CD-EWARM-6201-2590_mcu123.zip
    相关文件“IAR_EWARM5.4和谐文件.rar ”可以在GOOGLE上搜索到
    http://bbs.mcu123.net/bbs/thread-15164-1-1.html
    并下载:
    IAR_EWARM5[1].4和谐文件.rar

2,在http://www.nuvoton-m0.com/forum.php?mod=viewthread&tid=1&extra=page%3D1上
下载Nu-Link驱动“公测版驱动下载 v1.17.5218,支持最新的IAR 6.21”
  Nu-Link_IAR_Driver 1.17.5218.zip
http://www.nuvoton-m0.com/forum.php?mod=attachment&aid=MTg3fDI4NGFkNTk1fDEzMTUyOTkyOTF8MA%3D%3D
   
    下载ICP编程工具“NuMicro ICP Programming Tool 1.17.5218”
    NuMicro ICP Programming Tool 1.17.5218.zip
    http://www.nuvoton-m0.com/forum.php?mod=attachment&aid=MTg2fDI3YTFmZmJlfDEzMTUyOTkyOTF8MA%3D%3D

下载ISP编程工具“NuMicro ISP Programming Tool v1.41”
NuMicro ISP Programming Tool V1.41.zip
http://www.nuvoton-m0.com/forum.php?mod=attachment&aid=NDh8OTBkZjBjYTJ8MTMxNTI5OTI5MXww

下载NUC100系列基础程序库“NUC100Series BSP_CMSIS V1.05.001.7z”
NUC100SeriesBSP_v1.05.001.7z
http://www.nuvoton-m0.com/forum.php?mod=attachment&aid=NTR8YWY2YWI1Njd8MTMxNTMwMDA0OHww

3,在“http://dzstic.com/down.asp”上下载“NuTiny-SDK-NUC140.rar”文档
NuTiny-SDK-NUC140.rar
http://dzstic.com/upload/20110906/20110906162939454.rar

4,新唐官方资料网址
新唐CM0官方资料主页
http://www.nuvoton.com/hq/chs/Pages/default.aspx
   
二,建立CM0的EWARM+Nu-LINK开发环境

1,双击“IAR_EWARM5[1].4和谐文件.rar”,运行里面的“EWARM_FULL_ARM540.exe”,选择“Product”中的“Embedded Workbench For ARM v5.40”,然后点击“Generate”
把产生的“License key”“License number”密码和序列号记录下来;

2,双击“CD-EWARM-6201-2590_mcu123.zip”运行里面的“autorun.exe”,在“IAR Embedded Workbench For ARM”中选择“Install IAR Embedded Workbench”,按常规的软件安装方式
把“IAR Embedded Workbench For ARM”安装到电脑上;

3,双击“Nu-Link_IAR_Driver 1.17.5218.zip”运行里面的“Nu-Link_IAR_Driver 1.17.5218.exe”,便会在“C:\Program Files\Nuvoton Tools\Nu-Link_IAR”和“C:\Program Files
\IAR Systems\Embedded Workbench 6.0” 目录中安装上相关的“Nu-LINK”的驱动。

4,双击“NuMicro ICP Programming Tool 1.17.5218.zip”运行里面的“NuMicro ICP Programming Tool 1.17.5218.exe”,便会在“C:\Program Files\Nuvoton Tools\ICPTool”
目录中安装上相关的“ ICP Programming Tool”的工具。

三,建立CM0的EWARM基本工程

1,在电脑开始菜单中打开“IAR Embedded Workbench IDE”,在“EWARM”的IDE菜单中选择“Project”->“Create New Project”创建一个新工程,在“Create New Project”选择“OK”存储目录
到“D:\works\9G-CM0\9G-NUC140\prj”下面,工程名叫“nuc140.ewp”,点击“OK”完成,点击“File”下的“Save Workspace”保存工作空间到目录中的“nuc140.eww”;

2,在“D:\works\9G-CM0\nuc140”下建立文件夹“bsp”“drv”“inc”“src”,等子目录,在“D:\works\9G-CM0\9G-NUC140\prj”下建立子目录“config”,并把 “NUC100SeriesBSP_v1.05.001.7z”
的“NUC100SeriesBSP\NuvotonPlatform_IAR\Src\Driver”和“NUC100SeriesBSP\NuvotonPlatform_IAR\Include\Driver”解压到“D:\works\9G-CM0\9G-NUC140\bsp\Driver”目录,把“NUC100SeriesBSP\
NuvotonPlatform_IAR\Include\System”解压到“D:\works\9G-CM0\9G-NUC140\bsp\System”目录,把“NUC100SeriesBSP\CMSIS\CM0\DeviceSupport\Nuvoton\NUC1xx\startup\iar\startup_NUC1xx.s”解压到
“D:\works\9G-CM0\9G-NUC140\bsp\Boot”,把“NUC100SeriesBSP\CMSIS\CM0\DeviceSupport\Nuvoton\NUC1xx”下的H和C文件及“NUC100SeriesBSP\CMSIS\CM0\CoreSupport”下的H和C文件解压到
“D:\works\9G-CM0\9G-NUC140\bsp\Cmsis”;

3,在“EWARM”的IDE菜单中选择“Project”->“Options”中的“General Options”的“Target”中的“Device”中选择“Nuvoton NUC140xE”,在“Linker”菜单中选择“Linker configuration file”里选择
“override default”并填上“$PROJ_DIR$\config\NUC140_Flash.icf,在“Library Configuration”下的库选项用“FULL”在“Library Opitions”下的“printf”和“scanf”格式也用“FULL”;

4,在“Options for node 'nuc140'”的“Category:”中选择上“Debugger”,在“Setup”->“Driver”中选择“Third-Party Driver”,然后在“Third-Party Driver”选择驱动到
“C:\Program Files\Nuvoton Tools\Nu-Link_IAR\Nu-Link_IAR.dll”,在“C/C++ Compiler”下的“Preprocessor”下面的方框内填上:
$PROJ_DIR$\..\inc\
$PROJ_DIR$\..\bsp\
$PROJ_DIR$\..\bsp\Cmsis\
$PROJ_DIR$\..\bsp\Driver\

5,在“Debugger”的“Download”勾选择“Use flash loader”和“override default .board file”并填入“$TOOLKIT_DIR$\config\flashloader\Nuvoton\NUC100_APROM.board”,把
“C:\Program Files\Nuvoton Tools\Nu-Link_IAR\Samples\NUC140_PWM\config”下的“NUC140_Flash.icf”和“NUC140_Ram.icf”复制到“D:\works\9G-CM0\9G-NUC140\prj\config”,
把“C:\Program Files\Nuvoton Tools\Nu-Link_IAR\Samples\NUC140_PWM”下的“SH_retarget.c”和“SH_startup_NUCxxx_iar.s”复制到“D:\works\9G-CM0\9G-NUC140\bsp\Boot”;

6,在“IAR Embedded Workbench IDE”的“Workspace”下的“Files”中右击选择“Add”->“Add Group”并填入“sys”,另外同样建立“bsp”,“drv”,“src”等目录,然后在“sys”上右击
选择“Add”->“Add Files” 然后选择“D:\works\9G-CM0\9G-NUC140\bsp\Boot”下的“SH_retarget.c”,“SH_startup_NUCxxx_iar.s”和“D:\works\9G-CM0\9G-NUC140\bsp\Cmsis”下的
“core_cm0.c”和“system_NUC1xx.c”;同样用“Add”->“Add Files”把“D:\works\9G-CM0\9G-NUC140\bsp\Driver”的文件添加到“bsp”目录;(retarget.c和DrvUSB.c除外)

7,在“D:\works\9G-CM0\9G-NUC140\src”中建立“main.c”,然后添加到工程的“src”中,并在“main.c”中填入下面内容:
#include <stdio.h>
#include <stdint.h>
#include <Nuvoton\ionuc1xx.h>

int main(void)
{
     uint32_t i=0;
   
     /* Output a message on Hyperterminal using printf function */
  printf("\n\r\n\r\n\r\n\r");
  printf("*** 9G-NUC120 V1.00 Build by yuanxihua@21cn.com on ("__DATE__ " - " __TIME__ ")\n\r");
  printf("*** 9G-NUC120 V1.00 Rebooting ...\n\r\n\r");

  while(1)
  {
         GPA_DOUT =0xffff;
         for(uint32_t j = 0; j <1000000; j++);
         GPA_DOUT =0x0000;
         for(uint32_t j = 0; j <1000000; j++);
           
         printf("*** 9G-NUC140 V1.00 Running %d Times...\n\r",i++);
  }
}

(编译时会有与core_cm0.h与“C:\Program Files\IAR Systems\Embedded Workbench 6.0\arm\inc\c\intrinsics.h”相冲突时,
把有问题的uint32_t改回相应的 unsigned long即可;)

8,在“Debugger”的“Download”勾选择“Use flash loader”和“override default .board file”并填入“$TOOLKIT_DIR$\config\flashloader\Nuvoton\NUC100_LDROM.board”,可以把
相应的程序烧进LDROM区;

9,在“EWARM”的IDE菜单中选择“Nu-Link”->“ICP Programming Tool”中,可以不擦除整片FLASH直接改变配置位从APPROM区切换到LDROM区启动,FLASH的1能修改成0;

#53 Cortex M0/M3/M4/M7 » 9G-MINI51 新唐CM0+EWARM入门开发过程简介--缥缈九哥 » 2020-05-09 18:57:17

缥缈九哥
回复: 0

9G-MINI51 新唐CM0+EWARM入门开发过程简介

一,准备EWARM + 新唐CM0软件包

1,在http://www.mcu123.com/news/Soft/ShowSoftDown.asp?UrlID=1&SoftID=535 上
下载 IAR Embedded Workbench for ARM v6.20 FULL CD-EWARM-6201-2590 软件
CD-EWARM-6201-2590_mcu123.zip
    ftp://mcu123:mcu123@mcu123.com/已整理目录/开发工具软件/ARM/CD-EWARM-6201-2590_mcu123.zip
    相关文件“IAR_EWARM5.4和谐文件.rar ”可以在GOOGLE上搜索到
    http://bbs.mcu123.net/bbs/thread-15164-1-1.html
    并下载:
    IAR_EWARM5[1].4和谐文件.rar

2,在http://www.nuvoton-m0.com/forum.php?mod=viewthread&tid=2&extra=page%3D1上
下载Nu-Link驱动“公测版驱动下载 v1.17.5218,支持最新的IAR 6.21”
  Nu-Link_IAR_Driver 1.17.5218.zip
http://www.nuvoton-m0.com/forum.php?mod=attachment&aid=MTg3fDI4NGFkNTk1fDEzMTUyOTkyOTF8MA%3D%3D
   
    下载ICP编程工具“NuMicro ICP Programming Tool 1.17.5218”
    NuMicro ICP Programming Tool 1.17.5218.zip
    http://www.nuvoton-m0.com/forum.php?mod=attachment&aid=MTg2fDI3YTFmZmJlfDEzMTUyOTkyOTF8MA%3D%3D

下载ISP编程工具“NuMicro ISP Programming Tool v1.41”
NuMicro ISP Programming Tool V1.41.zip
http://www.nuvoton-m0.com/forum.php?mod=attachment&aid=NDh8OTBkZjBjYTJ8MTMxNTI5OTI5MXww

下载?M051软件库资源“M051SeriesBSP_CMSIS V1.02.001”和“M051SeriesBSP_RegCtrlPrg V1.00.002”
M051SeriesBSP_v1.02.001.zip
http://www.nuvoton-m0.com/forum.php?mod=attachment&aid=NDV8ZTc3MTg5M2V8MTMxNTM3NjExOHww
M051SeriesBSP_RegCtrlPrg.zip
http://www.nuvoton-m0.com/forum.php?mod=attachment&aid=NDZ8OTVlMjM1OGN8MTMxNTM3NjExOHww

3,在“http://dzstic.com/down.asp”上下载“NuTiny-EVB-Mini51_V002”文档
NuTiny-EVB-Mini51_V002.rar
http://dzstic.com/upload/20110907/20110907141832652.rar

4,新唐官方资料网址
新唐CM0官方资料主页
http://www.nuvoton.com/hq/chs/Pages/default.aspx
   
二,建立CM0的EWARM+Nu-LINK开发环境

1,双击“IAR_EWARM5[1].4和谐文件.rar”,运行里面的“EWARM_FULL_ARM540.exe”,选择“Product”中的“Embedded Workbench For ARM v5.40”,然后点击“Generate”
把产生的“License key”“License number”密码和序列号记录下来;

2,双击“CD-EWARM-6201-2590_mcu123.zip”运行里面的“autorun.exe”,在“IAR Embedded Workbench For ARM”中选择“Install IAR Embedded Workbench”,按常规的软件安装方式
把“IAR Embedded Workbench For ARM”安装到电脑上;

3,双击“Nu-Link_IAR_Driver 1.17.5218.zip”运行里面的“Nu-Link_IAR_Driver 1.17.5218.exe”,便会在“C:\Program Files\Nuvoton Tools\Nu-Link_IAR”和“C:\Program Files
\IAR Systems\Embedded Workbench 6.0” 目录中安装上相关的“Nu-LINK”的驱动。

4,双击“NuMicro ICP Programming Tool 1.17.5218.zip”运行里面的“NuMicro ICP Programming Tool 1.17.5218.exe”,便会在“C:\Program Files\Nuvoton Tools\ICPTool”
目录中安装上相关的“ ICP Programming Tool”的工具。

三,建立CM0的EWARM基本工程

1,在电脑开始菜单中打开“IAR Embedded Workbench IDE”,在“EWARM”的IDE菜单中选择“Project”->“Create New Project”创建一个新工程,在“Create New Project”选择“OK”存储目录
到“D:\works\9G-CM0\9G-MINI51\prj”下面,工程名叫“MINI51.ewp,点击“OK”完成,点击“File”下的“Save Workspace”保存工作空间到目录中的“MINI51.eww”;

2,在“D:\works\9G-CM0\9G-MINI51”下建立文件夹“bsp”“drv”“inc”“src”,等子目录,在“D:\works\9G-CM0\9G-MINI51\prj”下建立子目录“config”,并把 “M051SeriesBSP_v1.02.001.zip”
的“M051SeriesBSP\NuvotonPlatform_IAR\Src\Driver”和“M051SeriesBSP\NuvotonPlatform_IAR\Include\Driver”解压到“D:\works\9G-CM0\9G-MINI51\bsp\Driver”目录,把“M051SeriesBSP\
NuvotonPlatform_IAR\Include\System”解压到“D:\works\9G-CM0\9G-MINI51\bsp\System”目录,把“M051SeriesBSP\CMSIS\CM0\DeviceSupport\Nuvoton\M051Series\startup\iar\startup_M051Series.s”解压到
“D:\works\9G-CM0\9G-MINI51\bsp\Boot”,把“M051SeriesBSP\CMSIS\CM0\DeviceSupport\Nuvoton\M051Series”下的H和C文件及“M051SeriesBSP\CMSIS\CM0\CoreSupport”下的H和C文件解压到
“D:\works\9G-CM0\9G-MINI51\bsp\Cmsis”;

3,在“EWARM”的IDE菜单中选择“Project”->“Options”中的“General Options”的“Target”中的“Device”中选择“Nuvoton Mini51 series (Mini51,Mini52,Mini54)”,在“Linker”菜单中选择“Linker configuration file”里选择
“override default”并填上“$PROJ_DIR$\config\M052_Flash.icf”,在“Library Configuration”下的库选项用“FULL”在“Library Opitions”下的“printf”和“scanf”格式也用“FULL”;

4,在“Options for node 'MINI51'”的“Category:”中选择上“Debugger”,在“Setup”->“Driver”中选择“Third-Party Driver”,然后在“Third-Party Driver”选择驱动到
“C:\Program Files\Nuvoton Tools\Nu-Link_IAR\Nu-Link_IAR.dll”,在“C/C++ Compiler”下的“Preprocessor”下面的方框内填上:
$PROJ_DIR$\..\inc\
$PROJ_DIR$\..\bsp\
$PROJ_DIR$\..\bsp\Cmsis\
$PROJ_DIR$\..\bsp\Driver\

5,在“Debugger”的“Download”勾选择“Use flash loader”和“override default .board file”并填入“$TOOLKIT_DIR$\config\flashloader\Nuvoton\Mini51_APROM.board”,把
“C:\Program Files\Nuvoton Tools\Nu-Link_IAR\Samples\M052\config”下的“M052_Flash.icf”复制到“D:\works\9G-CM0\9G-MINI51\prj\config”,
把“C:\Program Files\Nuvoton Tools\Nu-Link_IAR\Samples\M052”下的“SH_retarget.c”和“SH_startup_M05x_iar.s”复制到“D:\works\9G-CM0\9G-MINI51\bsp\Boot”;

6,在“IAR Embedded Workbench IDE”的“Workspace”下的“Files”中右击选择“Add”->“Add Group”并填入“sys”,另外同样建立“bsp”,“drv”,“src”等目录,然后在“sys”上右击
选择“Add”->“Add Files” 然后选择“D:\works\9G-CM0\9G-MINI51\bsp\Boot”下的“SH_retarget.c”,“SH_startup_NUCxxx_iar.s”和“D:\works\9G-CM0\9G-MINI51\bsp\Cmsis”下的
“core_cm0.c”和“system_M051Series.c”;同样用“Add”->“Add Files”把“D:\works\9G-CM0\9G-MINI51\bsp\Driver”的文件添加到“bsp”目录;(retarget.c除外)

7,在“D:\works\9G-CM0\9G-MINI51\src”中建立“main.c”,然后添加到工程的“src”中,并在“main.c”中填入下面内容:

 #include <stdio.h>
 #include <stdint.h>
 #include <Nuvoton\iomini51.h>
 
 int main(void)
 {
     uint32_t i=0;
    
     /* Output a message on Hyperterminal using printf function */
  printf("\n\r\n\r");
  printf("*** 9G-MINI51 V1.00 Build by yuanxihua@21cn.com on ("__DATE__ " - " __TIME__ ")\n\r");
  printf("*** 9G-MINI51 V1.00 Rebooting ...\n\r\n\r");
 
     GPIO_P0_PMD = 0X5555;
     GPIO_P1_PMD = 0X5555;
     GPIO_P2_PMD = 0X5555;
     GPIO_P3_PMD = 0X5555;
     GPIO_P4_PMD = 0X5555;
     GPIO_P5_PMD = 0X5555;
 
     while(1)
     {
         for(uint32_t j = 0; j <800000; j++);
         GPIO_P0_DOUT = 0x5E; /* switch on LEDs                    */
   GPIO_P1_DOUT = 0xCA;
   GPIO_P2_DOUT = 0xAB;
   GPIO_P3_DOUT = 0x9A;
   GPIO_P4_DOUT = 0x55;//NO USE
         GPIO_P5_DOUT = 0XE2;
         for(uint32_t j = 0; j <800000; j++);
         GPIO_P0_DOUT = 0xAD; /* switch off LEDs                    */
   GPIO_P1_DOUT = 0xF7;
   GPIO_P2_DOUT = 0xD7;
   GPIO_P3_DOUT = 0xED;
   GPIO_P4_DOUT = 0xAA;//NO USE
         GPIO_P5_DOUT = 0XDD;
        
         printf("*** 9G-MINI51 V1.00 Running %d Times...\n\r",i++);
     }
 }

(编译时会有与core_cm0.h与“C:\Program Files\IAR Systems\Embedded Workbench 6.0\arm\inc\c\intrinsics.h”相冲突时,把有问题的uint32_t改回相应的 unsigned long即可。)

#54 Cortex M0/M3/M4/M7 » 基于新唐NUC120RD2BN的EBI接口的ILI9327的驱动程序--缥缈九哥 » 2020-05-09 18:56:16

缥缈九哥
回复: 0

本程序采用了新唐NUC120RD2BN带了EBI总线的CPU,因为ILI9327只有一个地址线RS,也就是命令,数据寄存器地址,而且又支持16位总线,所以把此地址线接到多余的ALE上,把ALE配置成GPIO模式,把ALE地址锁存的时序忽略掉,直接用EBI总线驱动ILI9327的数据总线。

      其余不多说,请查看源码文件:ili9327.c

文件内容如下:

* Includes ------------------------------------------------------------------*/
#include <stdio.h>
#include <NUC1xx.H>
#include "Driver\DrvSYS.h"
#include "Driver\DrvGPIO.h"
#include "Driver\DrvEBI.h"

#define TFT_BL                E_GPA, 15   /* PA.15 = TFT_BL   */
#define TFT_RST               E_GPA, 9   /* PA.9  = TFT_RST  */
#define TFT_DC                E_GPB, 6   /* PB.6  = TFT_DC   */

#define ILI9327_READ()    (*(__IO uint16_t *)(0x60000000))
#define ILI9327_DAT(DAT)    *(__IO uint16_t *)(0x60000000) = DAT
#define ILI9327_CMD(CMD)   {GPIOB->DOUT &= 0xffbf;*(__IO uint16_t *)(0x60000000) = CMD;GPIOB->DOUT |= 0x0040;}
 
/*
//make by yuanxihua@21cn.com
//BYD LCM
//BM240400-8790FTGB
//262K TFT 240RGB×400dots
//
//ILI9327 is a 262,144-color single-chip SoC driver for a-TFT liquid crystal display
//with resolution of 240RGBx432 dots, comprising a 720-channel source driver, a 432-channel
//gate driver, 233,280 bytes GRAM for graphic data of 240RGBx432 dots, and power supply circuit.
_________________________________________________
| NUC120RD2BN      ILI9327B |
|            |
| PA9  TFT_RST  ---->  RESET  |
| PA15 TFT_BL  ---->  BACKLIGHT |
| PB6  TFT_DC  ---->  RS   |
| NCS  TFT_CS  ---->  CS   |
| NWR  TFT_WR  ---->  WR   |
| NRD  TFT_RD  ---->  RD   |
| AD0  TFT_D0  <--->  DB0   |
| ...  ...   <--->  ...   |
| AD15 TFT_D15  <--->  DB15  |
|_______________________________________________|

*/
uint16_t color_table[16]={0x0000,0xf800,0x07e0,0x001f,0xf81f,0xffe0,0x07ff,0xffff,};

void EBI_Init(void)
{
 DRVEBI_CONFIG_T sEBIConfig;
 DRVEBI_TIMING_T sEBITiming;

 // Open EBI function
 sEBIConfig.eDataWidth  = E_DRVEBI_DATA_16BIT;
 sEBIConfig.eAddrWidth  = E_DRVEBI_ADDR_16BIT;
 sEBIConfig.u32BaseAddress  = DRVEBI_BASE_ADDR;
 sEBIConfig.u32Size    = DRVEBI_MAX_SIZE;
  DrvEBI_Open(sEBIConfig);

 // Disable nWRH & nWRL for EBI support
 outpw(&SYS->GPBMFP, inpw(&SYS->GPBMFP) & ~(0x3<<2));
 outpw(&SYS->ALTMFP, inpw(&SYS->ALTMFP) & ~(0x3<<13));

 // Configure EBI timing
// sEBITiming.eMCLKDIV = E_DRVEBI_MCLKDIV_1; // 1656.0 KHZ  //Display And Read ID ERROR!!!
// sEBITiming.eMCLKDIV = E_DRVEBI_MCLKDIV_2; // 1147.0 KHZ  //Display OK, But Read ID ERROR!!!
 sEBITiming.eMCLKDIV = E_DRVEBI_MCLKDIV_4; //  666.7 KHZ  //Display OK, And Read ID OK!!!
// sEBITiming.eMCLKDIV = E_DRVEBI_MCLKDIV_8; //  400.0 KHZ
// sEBITiming.eMCLKDIV = E_DRVEBI_MCLKDIV_16; //  211.9 KHZ
// sEBITiming.eMCLKDIV = E_DRVEBI_MCLKDIV_32; //  106.4 KHZ

  sEBITiming.u8ExttALE = 0;
 sEBITiming.u8ExtIR2R = 0;
 sEBITiming.u8ExtIW2X = 0;
 sEBITiming.u8ExttAHD = 0;
 sEBITiming.u8ExttACC = 0;
 DrvEBI_SetBusTiming(sEBITiming);
}

void ILI9327_READ_ID(void)
{
 uint16_t i;
 ILI9327_CMD(0xEF);    //Device Code Read
 printf("ILI9327 ID DATA: ");
 for(i=1;i<=6;i++){printf("%04x ",(uint16_t)ILI9327_READ());}
 printf("\n\r\n\r");
}
 
void ILI9327_RESET(void)
{
 //PA9 PA15 PB6 is defined as GPIO;
 outpw(&SYS->GPAMFP, inpw(&SYS->GPAMFP) & ~(0x1<< 9));
 outpw(&SYS->GPAMFP, inpw(&SYS->GPAMFP) & ~(0x1<<15));
 outpw(&SYS->GPBMFP, inpw(&SYS->GPBMFP) & ~(0x1<< 6));

 //TFT_RST TFT_DC TFT_BL is defined as Output;
 DrvGPIO_Open(TFT_RST, E_IO_OUTPUT);
 DrvGPIO_Open(TFT_DC , E_IO_OUTPUT);
 DrvGPIO_Open(TFT_BL , E_IO_OUTPUT);

 DrvGPIO_SetBit(TFT_DC );
 DrvGPIO_ClrBit(TFT_BL );
 DrvGPIO_SetBit(TFT_RST);
 DrvSYS_Delay(1000);
 DrvGPIO_ClrBit(TFT_RST);   // RESET LOW  >=   1 ms
 DrvSYS_Delay(2000);
  DrvGPIO_SetBit(TFT_RST);   // RESET HIGH >= 120 ms
 DrvSYS_Delay(200000);
}

void ILI9327_CLEAR(uint16_t color)
{
    uint16_t i,j;

 for(i=0;i<240;i++)
 { 
  for (j=0;j<400;j++) {ILI9327_DAT(color);}
 }
}
void Delay_1ms(int delay)
{
 uint32_t i;
 for(i=0;i<delay;i++)DrvSYS_Delay(1000);
}
void ILI9327_TEST(void)
{
 uint16_t i,color;

 printf("%s(%d): Running:  %s()\n\r",__FILE__,__LINE__,__FUNCTION__);

 while(1)
 {
  color = color_table[(i++)%8];
  printf("COLOR = 0x%04x \n\r",color);
  ILI9327_CLEAR(color);

  Delay_1ms(2000);   // 2s
 }
}

void ILI9327_Init(void)
{ 
 printf("*** ILI9327 Driver V1.00 Build by yuanxihua@21cn.com on ("__DATE__ " - " __TIME__ ")\n\r\n\r");

 EBI_Init();

 ILI9327_RESET();
 ILI9327_READ_ID();

    ILI9327_CMD(0xE9);  //
    ILI9327_DAT(0x20);
    ILI9327_CMD(0x11);   //exit_sleep_mode
    DrvSYS_Delay(100000); //100 ms

    ILI9327_CMD(0xD1);   //VCOM Control
    ILI9327_DAT(0x00);
    ILI9327_DAT(0x6b);
    ILI9327_DAT(0x18);
    ILI9327_CMD(0xD0);   //Power_Setting
    ILI9327_DAT(0x07);
    ILI9327_DAT(0x04);
    ILI9327_DAT(0x88);
    ILI9327_CMD(0x36);  //set_address_mode
    ILI9327_DAT(0x88);
    ILI9327_CMD(0xC1);  //Display_Timing_Setting for Normal/Partial Mode
    ILI9327_DAT(0x10);
    ILI9327_DAT(0x10);
    ILI9327_DAT(0x02);
    ILI9327_DAT(0x02);
    ILI9327_CMD(0xC0);   //Panel Driving Setting
    ILI9327_DAT(0x00);
    ILI9327_DAT(0x35);
    ILI9327_DAT(0x00);
    ILI9327_DAT(0x00);
    ILI9327_DAT(0x01);
    ILI9327_DAT(0x02);
    ILI9327_CMD(0xC5);   //Frame Rate Control
    ILI9327_DAT(0x02);
    ILI9327_CMD(0xD2);   //Power_Setting for Normal Mode
    ILI9327_DAT(0x01);
    ILI9327_DAT(0x44);
    ILI9327_CMD(0xC8);  //Gamma Setting
    ILI9327_DAT(0x00);
    ILI9327_DAT(0x56);
    ILI9327_DAT(0x45);
    ILI9327_DAT(0x04);
    ILI9327_DAT(0x03);
    ILI9327_DAT(0x01);
    ILI9327_DAT(0x23);
    ILI9327_DAT(0x12);
    ILI9327_DAT(0x77);
    ILI9327_DAT(0x40);
    ILI9327_DAT(0x09);
    ILI9327_DAT(0x06);
    ILI9327_DAT(0x88);
    ILI9327_DAT(0x88);
    ILI9327_DAT(0x88);
    ILI9327_CMD(0x3A);   //set_pixel_format
 ILI9327_DAT(0x55);   
 ILI9327_CMD(0x2A);  //set_column_address
 ILI9327_DAT(0x00);
 ILI9327_DAT(0x00);
 ILI9327_DAT(0x00);
 ILI9327_DAT(0xEF);
 ILI9327_CMD(0x2B);  //set_page_address
 ILI9327_DAT(0x00);
 ILI9327_DAT(0x20);
 ILI9327_DAT(0x01);
 ILI9327_DAT(0xAF);
 ILI9327_CMD(0x29);   //set_display_on
 ILI9327_CMD(0x2C);  //write_memory_start

 DrvGPIO_SetBit(TFT_BL );

 ILI9327_TEST();
}

void ILI9327_SLEEP(void)
{
 ILI9327_CMD(0x10);  //enter_sleep_mode
}
 
void ILI9327_WAKEUP(void)
{
 ILI9327_CMD(0x11);  //exit_sleep_mode
}


void EBI_test(void)
{
 uint32_t i,j=0; 
 uint32_t data;

 printf("%s(%d): Running:  %s()\n\r",__FILE__,__LINE__,__FUNCTION__);

 EBI_Init();

 printf("MCLK of EBI colck is %d KHz.\n\r", (DrvSYS_GetHCLKFreq()/4)/1000);

 //PA9 PB6 is defined as GPIO;
 outpw(&SYS->GPAMFP, inpw(&SYS->GPAMFP) & ~(0x1<<9));
 outpw(&SYS->GPBMFP, inpw(&SYS->GPBMFP) & ~(0x1<<6));

 //TFT_RST TFT_DC TFT_BLis defined as Output;
 DrvGPIO_Open(TFT_RST, E_IO_OUTPUT);
 DrvGPIO_Open(TFT_DC , E_IO_OUTPUT);
 DrvGPIO_Open(TFT_BL , E_IO_OUTPUT);
 DrvGPIO_Open(E_GPB, 1 , E_IO_OUTPUT); //LED test...

 DrvGPIO_SetBit(TFT_DC );
 DrvGPIO_SetBit(TFT_RST);
 DrvGPIO_ClrBit(TFT_BL );

 while(0)
 { 
  //test for write
  *(__IO uint16_t *)((uint32_t)0x60000000) = 0xffff;
  *(__IO uint16_t *)((uint32_t)0x60000000) = 0x0000;
 }
 while(0)
 {  
  //test for read
  data =  *(__IO uint16_t *)((uint32_t)0x60000000);
  printf("Running %d Times : D15-D0:%1d%1d%1d%1d%1d%1d%1d%1d_%1d%1d%1d%1d%1d%1d%1d%1dB\n\r",j++,
  (data>>15)&0x1,(data>>14)&0x1,(data>>13)&0x1,(data>>12)&0x1,
  (data>>11)&0x1,(data>>10)&0x1,(data>> 9)&0x1,(data>> 8)&0x1,
  (data>> 7)&0x1,(data>> 6)&0x1,(data>> 5)&0x1,(data>> 4)&0x1,
  (data>> 3)&0x1,(data>> 2)&0x1,(data>> 1)&0x1,(data>> 0)&0x1);
  for(i=0;i<0x200000;i++); //delay about 1 second
 }
 while(1)
 {
  printf("Running %d Times...\n\r",j++);
  //test for IO
  DrvGPIO_SetBit(TFT_RST);
  DrvGPIO_SetBit(TFT_DC );
  DrvGPIO_SetBit(TFT_BL );
  GPIOB->DOUT |= (1 << 1);
  for(i=0;i<0x200000;i++);
  DrvGPIO_ClrBit(TFT_RST);
  DrvGPIO_ClrBit(TFT_DC );
  DrvGPIO_ClrBit(TFT_BL );
  GPIOB->DOUT &= ~(1 << 1);

  for(i=0;i<0x200000;i++);
 }
}

文件结束。

#55 Cortex M0/M3/M4/M7 » 基于新唐M0的M0516LAN的SIM900A的驱动测试--缥缈九哥 » 2020-05-09 18:55:05

缥缈九哥
回复: 0

元旦放假,急于赶一个小项目,做了一个M0516LAN驱动SIM900A的测试。第一次用SIM900A,其中遇到几个小问题,调了好久,也问过群里用过SIM900A的几位朋友才调通,在此感谢。最弱智的问题是我把NRESET接到了PWM3上,然后又启动了PWM3,虽然后面把P43置成IO输出却不成功,然后大半晚上就那么悲剧掉了。新唐的库是置成了复用功能再想置回IO,需要先DrvGPIO_InitFunction(E_FUNC_GPIO);才能配置IO功能的。我后来还是不启动PWM就通过了开机过程。只要SIM900A开机了,NETLIGHT的LED就会闪烁,不管有没有SIM卡。另外,所有SIM900A的AT命令都是以“\r”结束的。

“sim900a.c ”文件源码如下:

#include <stdio.h>
#include <M051Series.h>

#include "Driver\DrvUART.h"
#include "Driver\DrvGPIO.h"
#include "Driver\DrvSYS.h"

#define PWRKEY   E_PORT2, E_PIN1
#define NRESET  E_PORT4, E_PIN3
#define STATUS   E_PORT2, E_PIN3
#define RI   E_PORT3, E_PIN2
#define CTS   E_PORT0, E_PIN0
/*
_________________________________________________
| M0516LAN      SIM900A  |
|            |
| P21  PWRKEY  ---->  PWRKEY  |
| P43  NRESET  ---->  NRESET  |
| P23  STATUS  <----  STATUS  |
| P32  RI   <----  RI   |
| P00  CTS1  <----  CTS   |
| P13  TXD1  ---->  RXD   |
| P12  RXD1  <----  TXD   |
|_______________________________________________|
*/
int UART1_init(void)
{
 STR_UART_T sParam;

 /* Set UART1 Pin */
 DrvGPIO_InitFunction(E_FUNC_UART1);
// outpw(&SYS->P1_MFP, (inpw(&SYS->P1_MFP) | (0x3<<10)) & ~(0x3<<2));
// outpw(&SYS->P0_MFP, (inpw(&SYS->P0_MFP) | (0x3<<8)) & ~(0x3<<0));

 /* Select UART1 Clock Source From 12Mhz*/
 DrvSYS_SelectIPClockSource(E_SYS_UART_CLKSRC,0);

 /* UART1 Setting */
    sParam.u32BaudRate   = 9600;
    sParam.u8cDataBits   = DRVUART_DATABITS_8;
    sParam.u8cStopBits   = DRVUART_STOPBITS_1;
    sParam.u8cParity   = DRVUART_PARITY_NONE;
    sParam.u8cRxTriggerLevel= DRVUART_FIFO_1BYTES;

 if(DrvUART_Open(UART_PORT1,&sParam) != E_SUCCESS)
 {
  printf("UART1 open failed\n");
  return FALSE;
 }
 /* Enable Interrupt and install the call back function */
// DrvUART_EnableInt(UART_PORT1, (DRVUART_RLSINT | DRVUART_RDAINT),UART1_INT_HANDLE);
  
 /* Disable Interrupt */
// DrvUART_DisableInt(UART_PORT1,DRVUART_RLSINT | DRVUART_THREINT | DRVUART_RDAINT);

 return TRUE;
}

int SIM900A_Open(void)
{
 int dly;

 DrvGPIO_ClrBit(PWRKEY);
 for(dly=0;dly<2000;dly++) DrvSYS_Delay(1000); //delay 1S
 DrvGPIO_SetBit(PWRKEY);

 for(dly=0;dly<3000;dly++) DrvSYS_Delay(1000); //delay 3S
 if(DrvGPIO_GetBit(STATUS))
 {
  printf("SIM900A Open Success!!!\n\r");
  return 1;
 }
 else
 { 
  printf("SIM900A Open Failure!!!\n\r");
  return 0;
 }
}

int SIM900A_Close(void)
{
 int dly;

 DrvGPIO_ClrBit(PWRKEY);
 for(dly=0;dly<6000;dly++) DrvSYS_Delay(1000); //delay 1S-5S
 DrvGPIO_SetBit(PWRKEY);

 for(dly=0;dly<4000;dly++) DrvSYS_Delay(1000); //delay 2S

 if(DrvGPIO_GetBit(STATUS))
 { 
  printf("SIM900A Close Failure!!!\n\r");
  return 1;
 }
 else
 { 
  printf("SIM900A Close Success!!!\n\r"); 
  return 0;
 }
}

int SIM900A_Reset(void)
{
 int dly;

 DrvGPIO_ClrBit(NRESET);
 DrvSYS_Delay(100);       //delay 20uS-50uS
 DrvGPIO_SetBit(NRESET);

 for(dly=0;dly<2000;dly++) DrvSYS_Delay(1000); //delay 2S
 if(DrvGPIO_GetBit(STATUS)==1)
  return 1;
 else
  return 0;
}
int SIM900A_init(void)
{
    int  ret =0;

 DrvGPIO_Open(STATUS,  E_IO_INPUT);
 DrvGPIO_Open(RI,   E_IO_INPUT);
 DrvGPIO_Open(CTS,   E_IO_INPUT);
 DrvGPIO_Open(PWRKEY,  E_IO_OUTPUT);
 DrvGPIO_Open(NRESET,  E_IO_OUTPUT);

 DrvGPIO_SetBit(PWRKEY);
 DrvGPIO_SetBit(NRESET);

 ret = SIM900A_Open();
 UART1_init();

 return ret;
}

int SIM900A_gets(char *buf)
{
 int ret=0;
 int dly=3000000;   // delay 3S

 while(dly-->1) 
 {
  if(UART1->FSR.RX_EMPTY == 0 )
  {
   *buf++ =UART1->DATA;//printf("%c",*(buf-1));
   ret++;dly=10000; //delay  10ms
  }
  DrvSYS_Delay(1);   //delay 1us
 }
 return ret;
}

void SIM900A_puts(const char *buf)
{
 while(*buf)
 {
  while(UART1->FSR.TX_FULL == 1); 
  UART1->DATA =(*buf++)&0xff;//printf("%c",*(buf-1));
 }
}

// AT+CPOWD=1   //Power down
// AT+CFUN=x    //Power Saving
// AT+CBC  //monitor the supply voltage
// AT+IPR=x  //fixed baud rate ,“RDY” is received
// AT+CSCLK=1 //enable the SLEEP mode
// AT+CMIC  //adjust the input gain level of microphone
// AT+SIDET  //set the side-tone level
// AT+CLVL  //adjust the output gain level
// AT+CADC  //read the voltage value on ADC 

void SIM900A_test(void)
{
 char buffer[128];

 printf("\n\r\n\r");
 printf("*** 9G-M0516 V1.00 Build by yuanxihua@21cn.com on ("__DATE__ " - " __TIME__ ")\n\r");
 printf("*** 9G-M0516 V1.00 Rebooting ...\n\r\n\r");

 SIM900A_init();
 
 printf("SIM900A_test Send AT COMMAND @ 9600 bps !!!\n\r");

// SIM900A_puts("ATI\r");
 SIM900A_puts("AT+GMM\r");
 if(SIM900A_gets(buffer)>0)
 {printf("\n\r%s\n\r",buffer);}
}

//源码完毕。--缥缈九哥调试通过。

半主机的调试信息如下:

*** 9G-M0516 V1.00 Build by yuanxihua@21cn.com on (Jan  3 2012 - 13:16:32)
*** 9G-M0516 V1.00 Rebooting ...

SIM900A Open Success!!!
SIM900A_test Send AT COMMAND @ 9600 bps !!!

AT+GMM
SIMCOM_SIM900A

OK

--缥缈九哥验证


读SIM卡电话本。
 
SIM900A_puts("AT+CPBS=\"SM\"\r");
读第一条电话本记录
  
//get SIM no.1 phoneid
SIM900A_puts("AT+CPBR=1,1\r");
memset(buffer,'\0',sizeof(buffer)); 
if(SIM900A_gets(buffer)>0) 
{printf("\n\r%s\n\r",buffer);}
for(i=0;i<11;i++)
{
//AT+CPBR=1,1
//+CPBR: 1,"13925101136",129,"yuanxihua"
// printf("\n\r%c",buffer[24+i]);
callphoneid[i]= buffer[24+i];
}
//
 
 
发中文短信。
SIM900A_puts("AT+CMGF=1\r"); //TEXT Mode
memset(buffer,'\0',sizeof(buffer)); 
if(SIM900A_gets(buffer)>0) 
{printf("\n\r%s\n\r",buffer);}
SIM900A_puts("AT+CSCS=\"UCS2\"\r"); //for CHINESE
memset(buffer,'\0',sizeof(buffer)); 
if(SIM900A_gets(buffer)>0)
{printf("\n\r%s\n\r",buffer);}
//不用配置短信服务中心号码
/*
SIM900A_puts("AT+CSCA=\"002B0038003600310033003800300030003200300030003500300030\",145\r"); //+8613800200500 短信中心号码
memset(buffer,'\0',sizeof(buffer));
if(SIM900A_gets(buffer)>0)
{printf("\n\r%s\n\r",buffer);}
*/
SIM900A_puts("AT+CSMP=17,167,0,25\r");
memset(buffer,'\0',sizeof(buffer)); 
if(SIM900A_gets(buffer)>0)
{printf("\n\r%s\n\r",buffer);}
// SIM900A_puts("AT+CMGS=\"00310033003900320035003100300031003100330036\"\r"); //13925101136 被叫号码,不固定,从SIM卡读。
SIM900A_puts("AT+CMGS=\"");
for(i=0;i<11;i++)
{
SIM900A_puts("003");
SIM900A_putchar(callphoneid[i]);
}
SIM900A_puts("\"\r");
memset(buffer,'\0',sizeof(buffer)); 
if(SIM900A_gets(buffer)>0) 
{printf("\n\r%s\n\r",buffer);}
SIM900A_puts("4F60597D ");
//你好   短信内容,UNICODE格式;
SIM900A_putchar(26); //<Ctrl+Z>
memset(buffer,'\0',sizeof(buffer)); 
if(SIM900A_gets(buffer)>0);
{printf("\n\r%s\n\r",buffer);}
打电话 
 
printf("SIM900A Phone a call  by AT-commond @ 9600 bps !!!\n\r");
// Call a phone
SIM900A_puts("ATD");
for(i=0;i<11;i++)
{
SIM900A_putchar(callphoneid[i]);
}
SIM900A_puts(";\r");
memset(buffer,'\0',sizeof(buffer)); 
if(SIM900A_gets(buffer)>0) 
{printf("\n\r%s\n\r",buffer);}
发英文短信 
 
printf("SIM900A Send a English SMS  by AT-commond @ 9600 bps !!!\n\r");
//init SIM900A for SMS
SIM900A_puts("AT+CMGF=1\r"); //TEXT Mode
memset(buffer,'\0',sizeof(buffer));
if(SIM900A_gets(buffer)>0) 
{printf("\n\r%s\n\r",buffer);}
SIM900A_puts("AT+CSCS=\"GSM\"\r");
memset(buffer,'\0',sizeof(buffer));
if(SIM900A_gets(buffer)>0) 
{printf("\n\r%s\n\r",buffer);}
//prepore config SIM900A for sendding a SMS
SIM900A_puts("AT+CMGS=\"+86");
for(i=0;i<11;i++)
{
SIM900A_putchar(callphoneid[i]);
}
SIM900A_puts("\"\r");
memset(buffer,'\0',sizeof(buffer));
if(SIM900A_gets(buffer)>0) 
{printf("\n\r%s\n\r",buffer);}
//send a SMS to SIM900A
SIM900A_puts("This a report from yuanxihua@21cn.com!!!\x1a");// \x1a = <Ctrl+Z>
memset(buffer,'\0',sizeof(buffer));
if(SIM900A_gets(buffer)>0)
{printf("\n\r%s\n\r",buffer);}

#56 8051/STC8/AT89C51/N76E003 » 9G-N79E8X 新唐N79E8X+Keil C51入门开发过程简介 » 2020-05-09 18:53:52

缥缈九哥
回复: 0

一,准备Keil C51 + 新唐N79E8X软件包

1,在http://www.mcu123.com/news/Soft/embsof/uc/201109/539.html
上点击“::下载地址:: ”下的“FTP下载地址1 ”,在弹出的网页上
http://www.mcu123.com/news/Soft/ShowSoftDown.asp?UrlID=1&SoftID=539
上再右击“下载地址:”后的“下载”选择“目标另存为”下载文件到本地硬盘。
    下载keil c51v9.05 KEIL V9  C51V905
文件名是:c51v905_mcu123.rar
ftp://mcu123.com/%D2%D1%D5%FB%C0%ED%C4%BF%C2%BC/%BF%AA%B7%A2%B9%A4%BE%DF%C8%ED%BC%FE/51/c51v905_mcu123.rar
(自己查找破解文件“keygen.exe”)

2,在http://www.nuvoton.com 上点开“8051 Microcontroller”下的“80C51 LPC Microcontroller”来打开网页
http://www.nuvoton.com/NuvotonMOSS/Community/ProductInfo.aspx?tp_GUID=6913c5ee-ddaa-464c-a71b-e7e57f056436
把“N79/W79 LPC Series - Industrial Temperature Grade ”下面的数据手册全部下载下来;

然后点击“Development Resources”子栏目中的“Development Tool”出现
http://www.nuvoton.com/NuvotonMOSS/Community/ProductInfo.aspx?tp_GUID=670aaf31-5d5c-45d3-8a9e-040e148d55cf
然后右击“Nuvoton 8051 Keil uVision Driver v1.02.zip”选择“目标另存为”下载文件到本地硬盘,
Nuvoton_8051_Keil_uVision_Driver_v1.02.zip
同样右击另存下载“Nuvoton ISP-ICP Programmer v6.00.zip”到本地硬盘;
Nuvoton+ISP-ICP+Programmer+v6.00.zip

退回上个网页
http://www.nuvoton.com/NuvotonMOSS/Community/ProductInfo.aspx?tp_GUID=6913c5ee-ddaa-464c-a71b-e7e57f056436
并点击“Development Resources”子栏目中的“Demo Code”出现
http://www.nuvoton.com/NuvotonMOSS/Community/ProductInfo.aspx?tp_GUID=515275c4-f6ae-4915-89ce-366fd8097efc
把“Demo Code”下面的所有例子代码包全部下载下来。

二,建立Keil C51+N79E8X开发环境

1,双击“c51v905_mcu123.rar”运行里面的“c51v905.exe”,一路的“NEXT”再“NEXT”,最后就会安装“PK51 Prof. Developrs Kit”到电脑上,
将会在桌面产生“Keil uVision4”的快捷方式;

2,双击和谐软件“keygen.exe”,把“uVision4”的“File->License Management”菜单里面的“CID”复制到keygen里面的CID框中,选择“TARGET”
为“C51”后点击“Generate”,把产生的序列号复制到前面“uVision4”的窗口中的“LIC”框中,点击“ADD LIC”便会解除编译限制;

3,双击“Nuvoton_8051_Keil_uVision_Driver_v1.02.zip”运行里面的“Nuvoton_8051_Keil_uVision_Driver_v1.02.EXE”,便会在KEIL目录中安装上
相关的“Nu-LINK ICE Bridge”的驱动。

三,建立Keil C51+N79E8X基本工程

1,在电脑开始菜单中打开“Keil uVision4”,在“uVision4”的IDE菜单中选择“Project”->“New uVision Project”创建一个新工程,在“Create New Project”选择存储目录
到“D:\works\9G-CM0\9G-N79E8X\prj”下面,工程名叫“9g-n79e8x.uvproj”;

2,接着在“select a CPU Data Base File”菜单中选择“Generic CPU Base”点击“OK”,选择“Nuvoton”公司下面的“N79E855”点击“OK”后确认复制启动代码“STARTUP.A51”和
加入到工程项目中,即可产生一个空工程,再点击全部保存项目,会在“D:\works\9G-CM0\9G-N79E8X\prj”目录中发现“9g-n79e8x.uvopt”和“9g-n79e8x.uvproj”,“STARTUP.A51”等文件;

3,在“D:\works\9G-CM0\9G-N79E8X”下建立“drv”,“inc”,“lst”,“obj”,“src”等子目录,

4,在“uVision4”的IDE菜单中选择“Project”->“Manage”->“Components,Environment,Books”打开“Components,Environment,Books”页面里的“Project Components”,
双击“Target1”改名为“N79E8X”,双击“Source Group 1”改名为“boot”再添加“lib”“drv”“src”“inc”等目录后点击“OK”。

5,在“uVision4”的IDE菜单中选择“File”->“New”后选择“File”->“Save”把新建立的文件保存到“D:\works\9G-CM0\9G-N79E8X\src”,文件名为“main.c”,右击项目窗口中的“src”选择“Add Files
to Group 'src'”并在“main.c”中填入下面内容:
  #include <stdio.h>
  #include "N79E855A.h"
 
  void delay_ms(unsigned ms)
  {
   unsigned int i,j;
   for(i=0;i<ms;i++){for(j=0;j<300;j++);}
  }
  void main(void)
  {
   while(1)
   {
    P0=P1=P2=P3=0x00;
    delay_ms(500);
    P0=P1=P2=P3=0xFF;
    delay_ms(500);
   }
  }
 
三,配置Keil C51+N79E8X基本工程

1,在“uVision4”的IDE菜单中选择“Project”->“Opitions for Target ‘N79E8X’”,在“Output”页面勾选“Create HEX File”,并在“Select Folder Objects”指定
目录到“D:\works\9G-CM0\9G-N79E8X\obj”,后点击“OK”,同样在“Listing”中在“Select Folder Listings”指定目录到“D:\works\9G-CM0\9G-N79E8X\lst”;

2,在“Opitions for Target ‘N79E8X’”的“Debug”页面选择用硬件仿真器“NUVOTON_8051_KEIL_Driver”或者“Nuvoton Nu-Link 8051 Debugger”勾选“Run to main{}”,
点击后面的“Setting”里面选择上“AP”,“2.7V”,“CHBDA=0xff”,“CBORST”,“XTAL1”,“CKF”和“22MHZ”后点击“Write Config”,页面的“Driver DLL:”
中填上“S8051.DLL”。

3,在“Opitions for Target ‘N79E8X’”的“Utilities”页面选择“Use Target Driver for Flash Programming”用 “NUVOTON_8051_KEIL_Driver”
或者“Nuvoton Nu-Link 8051 Debugger”勾选上“Update Target before Debugging”后在“Setting”里面的“Configure”,勾选择全部4个选项后点击“OK”再“OK”退出;

3,在“Opitions for Target ‘N79E8X’”的“C/C++”页面的“Include Paths”中填入“..\inc”。

四,调试CM0的MDK-ARM基本工程

1,点击在“uVision4”的IDE菜单中选择“Flash”->“Download”便会自己编译代码生成HEX文件并下载到目标板子中(N79E85J Tiny Board V002的板子要通过USB线接到电脑USB上);;

2,点击在“uVision4”的IDE菜单中选择“Debug”->“Start/Stop Debug session”进入调试状态,然后选择“Debug”->“Run”,全速运行,可以看到IO口上的LED在秒闪烁。

(全文完,缥缈九哥测试于2012-01-18在广州)

#57 8051/STC8/AT89C51/N76E003 » 基于中颖SH88F516驱动TM1640的LED数码管驱动程序 » 2020-05-09 18:53:15

缥缈九哥
回复: 0

应朋友要求,设计了一个游戏机的功夫宝宝的控制台板子,用一个SH88F516驱动两片TM1640的芯片,数码管用LN5461AS,驱动代码如下:

#include "SH88F516.h"
#include <stdio.h>                /* prototype declarations for I/O functions */

#define  U2DIN    P1_5
#define  U2SCLK    P1_6
#define  U1DIN    P3_7
#define  U1SCLK    P3_6
#define  TM1640_DELAY  1

//0 1 2 3 4 5 6 7 8 9 A B C D E F
const unsigned char code TM1640_CODE[16]={0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x77, 0X7F, 0x39, 0x3F, 0x79, 0x71};

const unsigned char code TM1640_CODEA[16] _at_ 0xe000;

void tm1640_display(unsigned char *led_data);

void tm1640_delay(unsigned int delay)
{
 unsigned int i;
 for(i=0;i<delay;i++);
}
void tm1640_start(void)
{
 U1DIN  = U2DIN  = 1;
 U1SCLK = U2SCLK = 1; tm1640_delay(TM1640_DELAY);
 U1DIN  = U2DIN  = 0; tm1640_delay(TM1640_DELAY);
 U1SCLK = U2SCLK = 0; tm1640_delay(TM1640_DELAY);
}

void tm1640_end(void)
{
 U1SCLK = U2SCLK = 0;
 U1DIN  = U2DIN  = 0; tm1640_delay(TM1640_DELAY);
 U1SCLK = U2SCLK = 1; tm1640_delay(TM1640_DELAY);
 U1DIN  = U2DIN  = 1;   tm1640_delay(TM1640_DELAY);
}

void tm1640_byte(unsigned char data1,unsigned char data2)
{
 unsigned int i;

 for(i=0;i<8;i++)
 {
  data1 = data1 >>1;   U1DIN =CY;
  data2 = data2 >>1;
  U2DIN =CY;    tm1640_delay(TM1640_DELAY);
  U1SCLK = U2SCLK = 1; tm1640_delay(TM1640_DELAY);
  U1SCLK = U2SCLK = 0; tm1640_delay(TM1640_DELAY);
 }
}

void tm1640_display(unsigned char *led_data)
{
 unsigned int i;

 P1M0 &= ~(1<<6 ); P1M1 |= 1<<6; //
 P1M0 &= ~(1<<5 ); P1M1 |= 1<<5; //
 P3M0 &= ~(1<<6 ); P3M1 |= 1<<6; //
 P3M0 &= ~(1<<7 ); P3M1 |= 1<<7; //


 tm1640_end();
 tm1640_start();
 tm1640_byte(0x40,0x40); // command1
 tm1640_end();

 tm1640_start();
 tm1640_byte(0xc0,0xc0); // command2
 for(i=0;i<16;i++)
 {
  tm1640_byte(TM1640_CODE[led_data[i]],TM1640_CODE[led_data[16+i]]);
 }
 tm1640_end();

 tm1640_start();
 tm1640_byte(0x8b,0x8b); // command3
 tm1640_end();
}

#58 Cortex M0/M3/M4/M7 » 基于STM32单片机的DES加密解密算法C源码--缥缈九哥 » 2020-05-09 18:52:14

缥缈九哥
回复: 1

有一STM32项目需要用到DES算法,从网上找了很多资料什么的,看的似是而非的,只好找以前一个ASCOM的基于8位机,16位机的IC卡电话机的DES源码移植过来使用,测试通过后公布,方便大家借鉴使用。

//以下是des.c文件全部:
//密钥:       B4 31 5B 86 9D 7D FA A2
//数据:       1F AD 61 A5 F7 19 77 14
//DES加密结果:4C 78 E9 1A F2 DA 9C D3

const uint8_t initial_tr[64] =
{
 57, 49, 41, 33, 25, 17,  9,  1,
 59, 51, 43, 35, 27, 19, 11,  3,
 61, 53, 45, 37, 29, 21, 13,  5,
 63, 55, 47, 39, 31, 23, 15,  7,
 56, 48, 40, 32, 24, 16,  8,  0,
 58, 50, 42, 34, 26, 18, 10,  2,
 60, 52, 44, 36, 28, 20, 12,  4,
 62, 54, 46, 38, 30, 22, 14,  6
};

const uint8_t final_tr[64] =
{
 39,  7, 47, 15, 55, 23, 63, 31,
 38,  6, 46, 14, 54, 22, 62, 30,
 37,  5, 45, 13, 53, 21, 61, 29,
 36,  4, 44, 12, 52, 20, 60, 28,
 35,  3, 43, 11, 51, 19, 59, 27,
 34,  2, 42, 10, 50, 18, 58, 26,
 33,  1, 41,  9, 49, 17, 57, 25,
 32,  0, 40,  8, 48, 16, 56, 24
};

const uint8_t swap[64] =
{
 33, 34, 35, 36, 37, 38, 39, 40,
 41, 42, 43, 44, 45, 46, 47, 48,
 49, 50, 51, 52, 53, 54, 55, 56,
 57, 58, 59, 60, 61, 62, 63, 64,
  1,  2,  3,  4,  5,  6,  7,  8,
  9, 10, 11, 12, 13, 14, 15, 16,
 17, 18, 19, 20, 21, 22, 23, 24,
 25, 26, 27, 28, 29, 30, 31, 32
};

const uint8_t key_tr1[56] =
{
 56, 48, 40, 32, 24, 16,  8,
  0, 57, 49, 41, 33, 25, 17,
  9,  1, 58, 50, 42, 34, 26,
 18, 10,  2, 59, 51, 43, 35,
 62, 54, 46, 38, 30, 22, 14,
  6, 61, 53, 45, 37, 29, 21,
 13,  5, 60, 52, 44, 36, 28,
 20, 12,  4, 27, 19, 11,  3
};

const uint8_t key_tr2[64] =
{
 0,  0, 13,  4, 16, 10, 23,  0,
 0,  0,  2,  9, 27, 14,  5, 20,
 0,  0, 22,  7, 18, 11,  3, 25,
 0,  0, 15,  1,  6, 26, 19, 12,
 0,  0, 40, 54, 51, 30, 36, 46,
 0,  0, 29, 47, 39, 50, 44, 32,
 0,  0, 43, 52, 48, 38, 55, 33,
 0,  0, 45, 31, 41, 49, 35, 28
};

const uint8_t etr[64] =
{
 0,  0, 31,  4,  0,  1,  2,  3,
 0,  0,  3,  8,  4,  5,  6,  7,
 0,  0,  7, 12,  8,  9, 10, 11,
 0,  0, 11, 16, 12, 13, 14, 15,
 0,  0, 15, 20, 16, 17, 18, 19,
 0,  0, 19, 24, 20, 21, 22, 23,
 0,  0, 23, 28, 24, 25, 26, 27,
 0,  0, 27,  0, 28, 29, 30, 31
};

const uint8_t ptr[32] =
{
 31, 14, 39, 44, 60, 23, 55, 36,
  4, 30, 46, 53, 12, 37, 62, 21,
  5, 15, 47, 29, 63, 54,  6, 20,
 38, 28, 61, 13, 45, 22,  7, 52
};

const uint8_t s[8][64] =
{
 {
  14,  4, 13,  1,  2, 15, 11,  8,  3, 10,  6, 12,  5,  9,  0,  7,
   0, 15,  7,  4, 14,  2, 13,  1, 10,  6, 12, 11,  9,  5,  3,  8,
   4,  1, 14,  8, 13,  6,  2, 11, 15, 12,  9,  7,  3, 10,  5,  0,
  15, 12,  8,  2,  4,  9,  1,  7,  5, 11,  3, 14, 10,  0,  6, 13
 },
 {
  15,  1,  8, 14,  6, 11,  3,  4,  9,  7,  2, 13, 12,  0,  5, 10,
   3, 13,  4,  7, 15,  2,  8, 14, 12,  0,  1, 10,  6,  9, 11,  5,
   0, 14,  7, 11, 10,  4, 13,  1,  5,  8, 12,  6,  9,  3,  2, 15,
  13,  8, 10,  1,  3, 15,  4,  2, 11,  6,  7, 12,  0,  5, 14,  9
 },
 {
  10,  0,  9, 14,  6,  3, 15,  5,  1, 13, 12,  7, 11,  4,  2,  8,
  13,  7,  0,  9,  3,  4,  6, 10,  2,  8,  5, 14, 12, 11, 15,  1,
  13,  6,  4,  9,  8, 15,  3,  0, 11,  1,  2, 12,  5, 10, 14,  7,
   1, 10, 13,  0,  6,  9,  8,  7,  4, 15, 14,  3, 11,  5,  2, 12
 },
 {
   7, 13, 14,  3,  0,  6,  9, 10,  1,  2,  8,  5, 11, 12,  4, 15,
  13,  8, 11,  5,  6, 15,  0,  3,  4,  7,  2, 12,  1, 10, 14,  9,
  10,  6,  9,  0, 12, 11,  7, 13, 15,  1,  3, 14,  5,  2,  8,  4,
   3, 15,  0,  6, 10,  1, 13,  8,  9,  4,  5, 11, 12,  7,  2, 14
 },
 {
   2, 12,  4,  1,  7, 10, 11,  6,  8,  5,  3, 15, 13,  0, 14,  9,
  14, 11,  2, 12,  4,  7, 13,  1,  5,  0, 15, 10,  3,  9,  8,  6,
   4,  2,  1, 11, 10, 13,  7,  8, 15,  9, 12,  5,  6,  3,  0, 14,
  11,  8, 12,  7,  1, 14,  2, 13,  6, 15,  0,  9, 10,  4,  5,  3
 },
 {
  12,  1, 10, 15,  9,  2,  6,  8,  0, 13,  3,  4, 14,  7,  5, 11,
  10, 15,  4,  2,  7, 12,  9,  5,  6,  1, 13, 14,  0, 11,  3,  8,
   9, 14, 15,  5,  2,  8, 12,  3,  7,  0,  4, 10,  1, 13, 11,  6,
   4,  3,  2, 12,  9,  5, 15, 10, 11, 14,  1,  7, 6,  0,  8,  13
 },
 {
   4, 11,  2, 14, 15,  0,  8, 13,  3, 12,  9,  7,  5, 10,  6,  1,
  13,  0, 11,  7,  4,  9,  1, 10, 14,  3,  5, 12,  2, 15,  8,  6,
   1,  4, 11, 13, 12,  3,  7, 14, 10, 15,  6,  8,  0,  5,  9,  2,
   6, 11, 13,  8,  1,  4, 10,  7,  9,  5,  0, 15, 14,  2,  3, 12
 },
 {
  13,  2,  8,  4,  6, 15, 11,  1, 10,  9,  3, 14,  5,  0, 12,  7,
   1, 15, 13,  8, 10,  3,  7,  4, 12,  5,  6, 11,  0, 14,  9,  2,
   7, 11,  4,  1,  9, 12, 14,  2,  0,  6, 10, 13, 15,  3,  5,  8,
   2,  1, 14,  7,  4, 10,  8, 13, 15, 12,  9,  0,  3,  5,  6, 11
 }
};

const uint8_t rots[16] =
{
 1,  1,  2,  2,  2,  2,  2,  2,  1,  2,  2,  2,  2,  2,  2,  1
};

const uint8_t bit_msk[8] =
{
 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01
};

uint8_t DES_Encrypt_key[8];
uint8_t DES_Decrypt_key[8];
uint8_t sub_keys[16][8]; //sub_keys[16][8]
uint8_t main_key[8];

        void    des(uint8_t*, uint8_t*, uint8_t, uint8_t*);
  void  FLASH_Read_KEYS(uint8_t key_index);
static  void    transpose (uint8_t*, uint8_t*, const uint8_t*, uint8_t);
static  void    rotate_l (uint8_t*);
static  void    compute_subkeys (uint8_t*);
static  void    f (uint8_t*, uint8_t*, uint8_t*);

/************************************************************************/
/*                                                                      */
/*      Module title:           des                                     */
/*      Module type:            des mainrutine                          */
/*                                                                      */
/*      Author:                 YXH                                     */
/*      Date:                   2012-07-13                              */
/*                                                                      */
/*      Last changed by:        YXH                                     */
/*      Date:                   2012-07-13                              */
/*                                                                      */
/*      Functional Description: Encipher and decipher 64 bits string    */
/*                              according to a 64 bits key string       */
/*                              The string format is shown below        */
/*                                                                      */
/*      input parameter 1:      pointer to 64 bits input string         */
/*                      2:      pointer to 64 bits key string           */
/*                      3:      boolean if false indicating enciphering */
/*                              if true dechiphering                    */
/*                      4:      pointer to a 64 bits output string      */
/************************************************************************/
/*                                                                      */
/*                      msb                     lsb                     */
/*                      bit                     bit                     */
/*                      +-- -- -- -- -- -- -- --+                       */
/*              addr    !1st                 8th!                       */
/*                      +-- -- -- -- -- -- -- --+                       */
/*              addr+1  !9th                16th!                       */
/*                      +-- -- -- -- -- -- -- --+                       */
/*                      :                       :                       */
/*                      :                       :                       */
/*                      +-- -- -- -- -- -- -- --+                       */
/*              addr+7  !57th               64th!                       */
/*                      +-- -- -- -- -- -- -- --+                       */
/*                                                                      */
/************************************************************************/

void des(uint8_t *plain_strng, uint8_t *key, uint8_t d, uint8_t *ciph_strng)

{
  uint8_t a_str[8], b_str[8], x_str[8];
  uint8_t i, j, *pkey, temp;

    for (i = 0; i < 8 ; ++i)
 {
  if (key[i] != main_key[i])
        {
   compute_subkeys(key);
   i = 7;
        }
 }
 
    transpose(plain_strng, a_str, initial_tr, 64);
    for (i=1; i < 17; ++i)
    {
  for (j=0; j < 8; ++j){b_str[j] = a_str[j];}
  
  if (!d)           /*enchipher*/
   pkey = &sub_keys[i-1][0];
  else                /*dechipher*/
   pkey = &sub_keys[16-i][0];
  
  for (j=0; j < 4; ++j){a_str[j] = b_str[j+4];}
  
  f(pkey, a_str, x_str);
  
  for (j=0; j < 4; ++j) {a_str[j+4] = b_str[j] ^ x_str[j];}
    }
   
    temp = a_str[0]; a_str[0] = a_str[4]; a_str[4] = temp;
    temp = a_str[1]; a_str[1] = a_str[5]; a_str[5] = temp;
    temp = a_str[2]; a_str[2] = a_str[6]; a_str[6] = temp;
    temp = a_str[3]; a_str[3] = a_str[7]; a_str[7] = temp;
    transpose(a_str, ciph_strng, final_tr, 64);

}

/************************************************************************/
/*                                                                      */
/*      Module title:           transpose                               */
/*      Module type:            des subrutine                           */
/*                                                                      */
/*      Author:                 YXH                                     */
/*      Date:                   2012-07-13                              */
/*                                                                      */
/*      Last changed by:        YXH                                     */
/*      Date:                   2012-07-13                              */
/*                                                                      */
/*      Functional Description: Permute n bits in a string, according   */
/*                              to a table describing the new order.    */
/*                              0 < n <= 64                             */
/*                                                                      */
/*      input parameter 1:      pointer to first byte in input string   */
/*                      2:      pointer to first byte in output string  */
/*                      3:      pointer to table describing new order   */
/*                      4:      number of bits to be permuted           */
/************************************************************************/

void transpose(uint8_t *idata, uint8_t *odata, const uint8_t *tbl, uint8_t n)
{
 const uint8_t *tab_adr;
 int i, bi_idx;

 tab_adr = &bit_msk[0];
 i = 0;
 
 do
    {odata[i++] = 0;}
 while (i < 8);

 i = 0;
 do
 {
        bi_idx = *tbl++;
        if (idata[bi_idx>>3] & tab_adr[bi_idx & 7])
  {
   odata[i>>3] |= tab_adr[i & 7];
  }
 }
 while (++i < n);
}

/************************************************************************/
/*                                                                      */
/*      Module title:           rotate_l                                */
/*      Module type:            des subrutine                           */
/*                                                                      */
/*      Author:                 YXH                                     */
/*      Date:                   2012-07-13                              */
/*                                                                      */
/*      Last changed by:        YXH                                  */
/*      Date:                   2012-07-13                              */
/*                                                                      */
/*      Functional Description: rotate 2 concatenated strings of 28     */
/*                              bits one position to the left.          */
/*                                                                      */
/*      input parameter 1:      pointer to first byte in key string     */
/*                                                                      */
/************************************************************************/

void rotate_l(uint8_t *key)
{
  uint8_t str_x[8];
  uint8_t i;

      for (i=0; i < 8; ++i) str_x[i] = key[i];
      for (i=0; i < 7; ++i)
      {
        key[i] = (key[i] << 1);
        if ((i < 6) && ((str_x[i+1] & 128) == 128))
          key[i] |= 1;
      }
      if (str_x[0] & 0x80 )
        key[3] |= 0x10;
      else
        key[3] &= ~0x10;
      if (str_x[3] & 0x08 )
        key[6] |= 0x01;
      else
        key[6] &= ~0x01;
}

/************************************************************************/
/*                                                                      */
/*      Module title:           compute_subkeys                         */
/*      Module type:            des subrutine                           */
/*                                                                      */
/*      Author:                 YXH                                     */
/*      Date:                   2012-07-13                              */
/*                                                                      */
/*      Last changed by:        YXH                                     */
/*      Date:                   2012-07-13                              */
/*                                                                      */
/*      Functional Description: Computes the 16 sub keys for use in the */
/*                              DES algorithm                           */
/*                                                                      */
/*      input parameter 1:      pointer to first byte in key string     */
/*      output           :      fills the array sub_keys[16][8] with    */
/*                              sub keys and stores the input key in    */
/*                              main_key[8]                             */
/************************************************************************/
void compute_subkeys(uint8_t *key)
{
 uint8_t i, j, ikey[8], okey[8];

 for (i=0; i < 8; ++i)
 {
  main_key[i] = key[i];
 }
 
 transpose(key, ikey, key_tr1, 56);
 
 for (i=0; i < 16; ++i)
    {
  for (j=0; j < rots[i]; ++j) {rotate_l(ikey);}
   transpose(ikey, okey, key_tr2,  64);
  for (j=0; j < 8; ++j)
  { sub_keys[i][j] = okey[j];}
    }

}

/************************************************************************/
/*                                                                      */
/*      Module title:           f                                       */
/*      Module type:            des subrutine                           */
/*                                                                      */
/*      Author:                 YXH                                     */
/*      Date:                   2012-07-13                              */
/*                                                                      */
/*      Last changed by:        YXH                                     */
/*      Date:                   2012-07-13                              */
/*                                                                      */
/*      Functional Description: The chipher function                    */
/*                                                                      */
/*      input parameter 1:      pointer to first byte in key string     */
/*                      2:      pointer to a 32 bit input string        */
/*                      3:      pointer to a 32 bit output string       */
/************************************************************************/
void f(uint8_t *skey, uint8_t *a_str, uint8_t *x_str)
{
 uint8_t e_str[8], y_str[8], z_str[8];
 uint8_t k;

 transpose(a_str, e_str, etr, 64);
 for (k=0; k < 8; ++k)
 {
        y_str[k] = (e_str[k] ^ skey[k]) & 63;
        z_str[k] = s[k] [y_str[k]];
 }
 transpose(z_str, x_str, ptr, 32);
}

//源码完毕

#59 Cortex M0/M3/M4/M7 » 基于新唐NUC123的FM25640C的驱动代码--缥缈九哥 » 2020-05-09 18:51:07

缥缈九哥
回复: 0

产品用到铁电存储,要用到5V环境,我还是选择用了FM25640C了。下面是基于新唐NUC123SeriesBSP_CMSIS_V1.01.002的测试代码,希望能抛砖引玉。谢谢。

/**************************************************************************//**
* @file fm25640c.c
* @version V1.00
* $author: yuanxihua@21cn.com
* $Date:  2013/01/03 11:33a $
* @brief  NUC123 Series FM25640C Driver Sample Code
*
* @note
* Copyright (C) 2013 Nuvoton Technology Corp. All rights reserved.
*
******************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include <stdio.h>
#include "NUC123Series.h"
/*
_________________________________________________
| NUC123SD4AN0     FM25640C |
|            |
| PC8  SS10  ---->  CS   |
| PC9  SPICLK1  ---->  SCK   |
| PC10 MISO10  <----  SO   |
| PC11 MOSI10  ---->  SI   |
|_______________________________________________|
*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
//#define  FM25640C_CS   PC8
#define  FM25640C_SIZE  8*1024
//FM25640C命令
#define   FM25640C_WREN  0x06
#define   FM25640C_WRDI  0x04
#define   FM25640C_RDSR  0x05ff
#define   FM25640C_WRSR  0x0100
#define   FM25640C_READ  0x030000FF
#define   FM25640C_WRITE  0x02000000
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
void FM25640C_Init(void);
void FM25640C_Write_Byte(uint32_t addr,uint8_t wrdata);
void FM25640C_Write_Status_Register(uint8_t wrdata);
uint8_t FM25640C_Read_Byte(uint32_t addr);
uint8_t FM25640C_Read_Status_Register(void);
void SPI1_Send_Data(uint32_t wrdata,uint8_t bits);
/* Private functions ---------------------------------------------------------*/
/**
  * @brief  Main program.
  * @param  None
  * @retval None
  */
void FM25640C_Test(void)
{
uint32_t i;
/* Configure the FM25640C */
FM25640C_Init();
while(0)
{
//  SPI1_Send_Data(0x55, 8);
//  SPI_SET_SS0(SPI1); SPI1_Send_Data(0x55, 8);SPI_CLR_SS0(SPI1); //写0x55测试SPI接口
//  FM25640C_Write_Byte(0xCC, 0x55);
//  FM25640C_Read_Byte (0xCC);
//  FM25640C_Read_Status_Register();
}
FM25640C_Write_Status_Register(0x00);
printf("FM25640C_Read_Status_Register() = 0x%02x \n\r",FM25640C_Read_Status_Register());
FM25640C_Write_Byte(0xAA, 0x55);
FM25640C_Write_Byte(0x55, 0xAA);
printf("FM25640C_Read_Byte(0xAA) = 0x%02x \n\r",FM25640C_Read_Byte(0xAA));
printf("FM25640C_Read_Byte(0x55) = 0x%02x \n\r",FM25640C_Read_Byte(0x55));
while(1)
{
  for(i=0;i<FM25640C_SIZE;i++)
  {FM25640C_Write_Byte(i, i&0xff);}
  SYS_SysTickDelay(300000);
  for(i=0;i<FM25640C_SIZE;i++)
  {
   //for display
   if((i%16)== 0){printf("\n\r%08xh:",i);}
   printf(" %02x",FM25640C_Read_Byte(i));
   if((i%16)==15){printf(" ;");}
   //display  end
  }
  SYS_SysTickDelay(300000);
}
}
// SPI1_Send_Data(FM25640C_WREN,8);
// SPI1_Send_Data(FM25640C_WRDI,8);
uint8_t FM25640C_Read_Byte(uint32_t addr)
{
uint32_t rddata,tmpdata=FM25640C_READ;
tmpdata |= (addr << 8);  
SPI1_Send_Data(tmpdata,32);
rddata = SPI_GET_RX0_DATA(SPI1);
return (uint8_t)rddata;
}
void FM25640C_Write_Byte(uint32_t addr, uint8_t wrdata)
{
uint32_t tmpdata=FM25640C_WRITE;
SPI1_Send_Data(FM25640C_WREN,8);    //中:使能写操作//Write Enable
tmpdata |= (addr << 8) + wrdata;
SPI1_Send_Data(tmpdata,32);
}
uint8_t FM25640C_Read_Status_Register(void)
{
uint32_t rddata;
SPI1_Send_Data(FM25640C_RDSR,16);
rddata = SPI_GET_RX0_DATA(SPI1);
return (uint8_t)rddata;
}
void FM25640C_Write_Status_Register(uint8_t wrdata)
{
uint16_t dat=FM25640C_WRSR | wrdata;
SPI1_Send_Data(FM25640C_WREN,8);    //中:使能写操作//Write Enable
SPI1_Send_Data(dat,16);
}
void SPI1_Send_Data(uint32_t wrdata, uint8_t bits)
{
SPI1->CNTRL = (SPI1->CNTRL&0xFFFFFF07) | ((bits&0x1f) <<3);
SPI_WRITE_TX0(SPI1, wrdata);     //中:待发数据//en:data waiting for sending
SPI_SET_GO(SPI1);        //中:启动发送//en: Start Transfer
while(SPI_IS_BUSY(SPI1) !=0);     //中:等待发送结束//en:waiting for sending finished
}
void SPI1_Init(void)
{
/* Enable IP clock */         
    SET_SPI1_CLKSRC(CLK_SPI1_HCLK);        //En:Select SPI1 clock source
    GPIO_SPI1();                                //中:配置PC8~11为SPI功能//Set PC11~PC8 as SPI1 pin. PC8=SPISS10,PC9=SPICLK1,PC10=MISO10,PC11=MOSI10
DrvSPI_Init(SPI1, SPI_MASTER, SPI_TYPE0, 32);
  SPI_SET_DIVIDER(SPI1, 1);                       //中:设置SPI的分频值//en:Set divider of SPI_CLK  SPIclk = Pclk/((DIVIDER+1)*2)
    SPI_SET_MSB_FIRST(SPI1);        //En:MSB first
SPI_SET_SS(SPI1, SPI_SS_LOW_TRIGGER, SPI_AUTO_SS);//中:自动片选选择//en:Slave Select auto
SPI_SET_SS0(SPI1);        //中:置片选有效//En:active SS1
}
void FM25640C_Init(void)
{
SPI1_Init();
}

//程序完毕。

#60 Cortex M0/M3/M4/M7 » 基于新唐MINI54LAN的TM1668的驱动设计--缥缈九哥 » 2020-05-09 18:50:05

缥缈九哥
回复: 0

某个朋友的项目,用到TM1668做LED显示和键盘驱动,我给他写了一个例子,现在公开给大家参考,希望有用。

/* Includes ------------------------------------------------------------------*/
#include <stdio.h>
#include <MINI51.H>
#include "Driver\DrvSYS.h"
#include "Driver\DrvSPI.h"
#include "Driver\DrvGPIO.h"
/*  
//make by yuanxihua@21cn.com
____________________________________________
| MINI51LAN       TM1668  |
|            |
| P04 SS   ---->  LSTB  |
| P05 MOSI   ---->  LDIO  |
| P06 MISO   ---->  LDIO  |
| P07 SCLK  <--->  LCLK  |
|___________________________________________|
*/
#define TM1668_STB   E_GPC, 7  /* PC.7 */
#define TM1668_CLK   E_GPC, 6   /* PC.6 */
#define TM1668_DIO   E_GPA, 13  /* PA.13 */
#define DISP_DELAY   2
//0 1 2 3 4 5 6 7 8 9 A B C D E F
const unsigned char  TM1668_CODE[16]={0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x77, 0X7F, 0x39, 0x3F, 0x79, 0x71};
const unsigned short TM1668_LINE[10]={0x200,0x300,0x380,0x3C0,0x3E0,0x3F0,0x3F8,0x3FC,0x3FE,0x3FF};
void TM1668_init(void);
void TM1668_Write_ADDR_INC(uint8_t *WrData);
void TM1668_Write_Byte(uint8_t WrData);
void TM1668_Read_KEY(uint8_t *RdData);
void TM1668_Test(void)
{
unsigned char wrbuff[14];
unsigned char rdbuff[5];
unsigned char key[7];
unsigned char led[7];
TM1668_init();
    while(1)
    {
//  TM1668_Write_Byte(0x55);
  TM1668_Read_KEY(rdbuff);
  key[1] = (rdbuff[0]&0x01)?1:0;
  key[2] = (rdbuff[0]&0x08)?1:0;
  key[3] = (rdbuff[1]&0x01)?1:0;
  key[4] = (rdbuff[1]&0x08)?1:0;
  key[5] = (rdbuff[0]&0x02)?1:0;
  key[6] = (rdbuff[0]&0x10)?1:0;
  led[1] = key[1]?1:0;
  led[2] = key[2]?1:0;
  led[3] = key[3]?1:0;
  led[4] = key[4]?1:0;
  led[5] = key[5]?1:0;
  led[6] = key[6]?1:0;
  wrbuff[0] = (led[6]<<5)|(led[5]<<4)|(led[4]<<3)|(led[3]<<2)|(led[2]<<1)|(led[1]<<0);
  printf("*** 9G-MINI51 V1.00 %02x...\n\r",wrbuff[0]);
  TM1668_Write_ADDR_INC(wrbuff);
    }
}
void TM1668_init(void)
{
    /* 设置SPI I/O    */
    DrvGPIO_InitFunction(FUNC_SPI);
   
    /* 设置SPI为主模式, 32-bit 传输    */
    DrvSPI_Open(eDRVSPI_MASTER, eDRVSPI_TYPE1, 32);
   
    /* 配置传输时的比特优先次序为LSB优先     */
    DrvSPI_SetEndian(eDRVSPI_LSB_FIRST);
   
    /* 关闭自动片选功能    */
    DrvSPI_DisableAutoSS();
   
    /* 设置片选信号启动电平为片选信号低电平或者下降沿启动    */
    DrvSPI_SetSlaveSelectActiveLevel(eDRVSPI_ACTIVE_LOW_FALLING);
   
    /* 设置SPI时钟速度为 12MHz    */
    DrvSPI_SetClockFreq(12000000, 0);
}
void TM1668_Write_Byte(uint8_t WrData)
{
    uint32_t SPI_Data = WrData;
    /* 设置SPI长度为8个位元    */
    DrvSPI_SetBitLength(8);
    /* 片选脚设为启动状态   */
    DrvSPI_SetSS();
    /* 传送WrData */
SPI_Data = 0x03;//Command1: 显示模式设置命令
    DrvSPI_SingleWrite(&SPI_Data);
    /* 等待传送退出    */
    while (DrvSPI_IsBusy());
    /* 片选脚设为非启动状态   */
    DrvSPI_ClrSS();
}
void TM1668_Write_ADDR_INC(uint8_t *WrData)
{
    uint32_t i,SPI_Data;
    /* 设置SPI长度为8个位元    */
    DrvSPI_SetBitLength(8);
    /* 片选脚设为启动状态   */
    DrvSPI_SetSS();
    /* 传送WrData */
SPI_Data = 0x03;//Command1: 显示模式设置命令
    DrvSPI_SingleWrite(&SPI_Data);
    /* 等待传送退出    */
    while (DrvSPI_IsBusy());
    /* 片选脚设为非启动状态   */
    DrvSPI_ClrSS();
    /* 片选脚设为启动状态   */
    DrvSPI_SetSS();
    /* 传送WrData */
SPI_Data = 0x40;//Command2: 数据读写设置命令
    DrvSPI_SingleWrite(&SPI_Data);
    /* 等待传送退出    */
    while (DrvSPI_IsBusy());
    /* 片选脚设为非启动状态   */
    DrvSPI_ClrSS();
    /* 片选脚设为启动状态   */
    DrvSPI_SetSS();
    /* 传送WrData */
SPI_Data = 0xC0;//Command3: 显示地址设置命令
    DrvSPI_SingleWrite(&SPI_Data);
    /* 等待传送退出    */
    while (DrvSPI_IsBusy());
for(i=0;i<14;i++)//Data1~n: 显示数据,以Command3指定的地址为起始地址(最多14 bytes)
{
  /* 传送WrData */
  SPI_Data = WrData;
  DrvSPI_SingleWrite(&SPI_Data);
  /* 等待传送退出    */
  while (DrvSPI_IsBusy());
}
    /* 片选脚设为启动状态   */
    DrvSPI_SetSS();
    /* 传送WrData */
SPI_Data = 0x88;//Command4: 显示控制命令
    DrvSPI_SingleWrite(&SPI_Data);
    /* 等待传送退出    */
    while (DrvSPI_IsBusy());
    /* 片选脚设为非启动状态   */
    DrvSPI_ClrSS();
}
void TM1668_Read_KEY(uint8_t *RdData)
{
    uint32_t i,SPI_Data;
    /* 设置SPI长度为8个位元    */
    DrvSPI_SetBitLength(8);
    /* 片选脚设为启动状态   */
    DrvSPI_SetSS();
    /* 传送WrData */
SPI_Data = 0x42;//Command4: 显示控制命令
    DrvSPI_SingleWrite(&SPI_Data);
    /* 等待传送退出    */
    while (DrvSPI_IsBusy());
    for (i = 0; i < 5; i++)
    {
        /* 读取资料    */
        SPI_Data = 0xffffffff;
        DrvSPI_SingleWrite(&SPI_Data);
     /* 等待传送退出    */
        while (DrvSPI_IsBusy());
  /* 从Rx寄存器内读取资料    */
        DrvSPI_DumpRxRegister(&SPI_Data, 1);
        RdData = (uint8_t) SPI_Data;
    }
    /* 片选脚设为非启动状态   */
    DrvSPI_ClrSS();
}

--代码完毕。

#61 Cortex M0/M3/M4/M7 » 基于新唐M0的XXTEA加密解密算法源码--缥缈九哥 » 2020-05-09 18:48:50

缥缈九哥
回复: 5

基于新唐M0的XXTEA加密解密算法源码

/*---------------------------------------------------------------------------------------------------------
    在数据的加解密领域,算法分为对称密钥与非对称密钥两种。对称密钥与非对称密钥由于各自的特点,所应用的领域是不尽相
同的。对称密钥加密算法由于其速度快,一般用于整体数据的加密,而非对称密钥加密算法的安全性能佳,在数字签名领域得到广
泛的应用。
    TEA算法是由剑桥大学计算机实验室的David Wheeler和Roger Needham于1994年发明,TEA是Tiny Encryption Algorithm的缩写,
以加密解密速度快,实现简单著称。TEA算法每一次可以操作64bit(8byte),采用128bit(16byte)作为key,算法采用迭代的形式,
推荐的迭代轮数是64轮,最少32轮。为解决TEA算法密钥表攻击的问题,TEA算法先后经历了几次改进,从XTEA到BLOCK TEA,直至
最新的XXTEA。XTEA也称做TEAN,它使用与TEA相同的简单运算,但四个子密钥采取不正规的方式进行混合以阻止密钥表攻击。
    Block TEA算法可以对32位的任意整数倍长度的变量块进行加解密的操作,该算法将XTEA轮循函数依次应用于块中的每个字,并且
将它附加于被应用字的邻字。XXTEA使用跟Block TEA相似的结构,但在处理块中每个字时利用了相邻字,且用拥有两个输入量的
MX函数代替了XTEA轮循函数。本文所描述的安全机制采用的加密算法就是TEA算法中安全性能最佳的改进版本-XXTEA算法。
    XXTEA算法的结构非常简单,只需要执行加法、异或和寄存的硬件即可,且软件实现的代码非常短小,具有可移植性,非常适合
嵌入式系统应用。由于XXTEA算法的以上优点,可以很好地应用于嵌入式RFID系统当中。

---------------------------------------------------------------------------------------------------------*/
#include <string.h>
#include <stdio.h>

#define MX (z>>5^y<<2) + (y>>3^z<<4)^(sum^y) + (k[p&3^e]^z)

//注意:delta的取值是随机的,但是为了避免不良的取值,采取的是
//黄金分割数(根号5-2)/2与2的32次方的乘积。为0x9e3779b9。  
//在解密中,sum=delta×round,如:delta×32=13C6EF3720
  
//v表示为运算的长整型数据的首地址
//k为长整型的密钥的首地址
//n表示以32bit为基本单位的要运算的组元个数,正表示加密,负表示解密

long xxtea(long* v, long n, long* k);

long xxtea(long* v, long n, long* k)
{
 unsigned long z=v[n-1], y=v[0], sum=0, e, DELTA=0x9e3779b9;
 long p, q;

 if(n > 1)
 {/* 加密过程 */
  q = 6 + 52/n;
  while(q-- > 0)
  {
   sum += DELTA; e = (sum >> 2) & 3;
   for (p=0; p<n-1; p++) y = v[p+1], z = v[p] += MX;
   y = v[0]; z = v[n-1] += MX;
  }
  return 0;
 }
 else
 if(n < -1)
 {/* 解密过程 */
  n = -n; q = 6 + 52/n; sum = q*DELTA;
  while(sum != 0)
  {
   e = (sum >> 2) & 3;
   for (p=n-1; p>0; p--) z = v[p-1], y = v[p] -= MX;
   z = v[n-1]; y = v[0] -= MX; sum -= DELTA;
  }
  return 0;
 } 
 return 1;
}

void  xxtea_test(void)
{
 unsigned long buff[4];
 unsigned long test[4]={0x11223344,0x55667788,0x99AABBCC,0xDDEEFF00};
 unsigned long keys[4]={0x12345678,0x9ABCDEF0,0x12345678,0x9ABCDEF0};
 
 while(1)
 {
  printf("\n\rxxtea test: \n\r");
  memcpy(buff,test,16); printf("0x%08x,0x%08x,0x%08x,0x%08x\n\r",buff[0],buff[1],buff[2],buff[3]);
  xxtea( buff, 4,keys); printf("0x%08x,0x%08x,0x%08x,0x%08x\n\r",buff[0],buff[1],buff[2],buff[3]);
  xxtea( buff,-4,keys); printf("0x%08x,0x%08x,0x%08x,0x%08x\n\r",buff[0],buff[1],buff[2],buff[3]);
  
  while(1);
 }
}

//--缥缈九哥收集整理

#62 Cortex M0/M3/M4/M7 » 基于MDK的ARM-GCC开发环境建立及新唐M0的HID类设备的C++开发--缥缈九哥 » 2020-05-09 18:47:46

缥缈九哥
回复: 1

一,下载安装测试arm-none-eabi-gcc编译工具链
1,查看arm-none-eabi-gcc编译工具版本
        打开网页:https://sourcery.mentor.com/GNUT ... db0be6eb3fb4a618248
        有关详细的工具手册。
       
2,下载arm-none-eabi-gcc编译工具链
        打开网页:https://sourcery.mentor.com/GNUToolchain/release2322
        下载文件:arm-2012.09-63-arm-none-eabi-i686-mingw32.tar.bz2
        详细连接:https://sourcery.mentor.com/GNUT ... 686-mingw32.tar.bz2
3,安装arm-none-eabi-gcc编译工具链
        把arm-2012.09-63-arm-none-eabi-i686-mingw32.tar.bz2解压到目录:C:\Sourcery\
        或者下载:arm-2012.09-63-arm-none-eabi.exe并且安装(详细连接:https://sourcery.mentor.com/GNUT ... 3-arm-none-eabi.exe)
       
4,配置系统环境变量
        右击“我的电脑”->“属性”->“高级”->“环境变量”->“系统变量”选择“Path”后点击“编辑”出现“编辑系统变量”
        后在“变量值”后增加“;C:\Sourcery\arm-2012.09\bin;C:\Sourcery\arm-2012.09\arm-none-eabi\bin”后连续按三次“确定”。
       
4,测试arm-none-eabi-gcc编译工具链
        在开始菜单中打开“运行”,执行cmd.exe,然后在里面执行命令:arm-none-eabi-gcc -v
        然后查看版本是不是:gcc version 4.7.2 (Sourcery CodeBench Lite 2012.09-63)
二,建立MDK环境
1,在“D:\works\9G-CM0\HID\prj”下新建MDK空工程“hid.uvproj”,并且在“prj”下建立“obj”和“lst”文件夹,
在“D:\works\9G-CM0\HID”下建立“inc”和“src”目录;
2,点开“project->manage”下的“Components,Environment and Books”,中间的一页“Folders/Extensions”,
勾选“Use GCC”,并且“GNU-Tool-Prefix”用“arm-none-eabi-”,“GNU-Tool folder”用“C:\Sourcery\arm-2012.09”
3,配置工程“Options”,obj文件放到“prj\obj”,lst文件放到“prj\lst”,在“User”的编译结束
后执行“arm-none-eabi-size !L.elf”来生成的ELF目标码的大小提示;
4,在“CC”页面勾选“Compile Thumb Code”,“Optimiation”用“Level 2 (speed)”,“Warning”用“Level 1”,
在“Misc Controls”用“-pipe -ffunction-sections -fdata-sections -fshort-wchar -gstrict-dwarf -finline-limit=100000000”
5,在“Linker”页面的选择不用系统库及启动文件,连接脚本用“.\nuc122_usb.ld”,“Misc Control” 用:
“-Wl,--relax -Wl,--gc-sections -Wl,-z -Wl,max-page-size=0”
6,然后在工程树中的“Target1”下面创建文件组“Configuration”“C++ Source”“C Source”和“Document”
右击“C++ Source”修改它的“Options”->“CC”的“Include Paths”用“..\inc”,而“Misc Controls”为:
“-std=c++11 -fno-rtti -fno-exceptions -Wno-pmf-conversions”
7,需要下载整个工程源码的可以与我联系。
三,测试HID通信
1,打开“Bus Hound 6.01”软件,选择“Devices”页面,勾选上“Auto select hot plugged devices”,然后把HID工程编译下载到目标板
        NUC123-TINY后运行,听到电脑“冬叮”一声,会自动选择上要监测的“(37)USB人体学输入设备”和“(38)HID-compliant device”;
2,把“(38)HID-compliant device”前的勾去掉,双击“(37)USB人体学输入设备”出现命令发送窗口,选择到“USB”页,点选端点中的
        “interput Out”,“data length”填写“64”,再在下面的“Hex Bytes”中填入64个字节的“55”;
3,在“Bus Hound 6.01”的“Capture”页面的右下角点击上“Run”,再到刚才的“USB”命令页面上面的“Run”按钮,就可以把64个
        BYTE的0x55发送给HID从设备;
       
4,在“Bus Hound 6.01”的“Capture”页面的数据窗口,你就能看到USB发送了64个0x55并且接收到64个0xaa。测试正确。完毕。
--感谢lee老师(j.y.lee@yeah.net)的指导及帮助

代码可以到这个地址下载:http://bbs.21ic.com/icview-413678-1-1.html

#63 Qt/MSVC/MINGW/C++/MFC/GTK+/Delphi/BCB » 利用OllyDbg和Enigma Virtual Box对WINDOWS下的MinGW4.9.1的Qt-5.4.0程序打包方法--缥缈九哥 » 2020-05-09 18:46:44

缥缈九哥
回复: 1

利用OllyDbg和Enigma Virtual Box对WINDOWS下的MinGW4.9.1的Qt-5.4.0程序打包方法
1,下载 odbg201.zip
        打开网页:http://www.ollydbg.de/version2.html
        下载文件:odbg201.zip
        详细连接:http://www.ollydbg.de/odbg201.zip
2,下载 Enigma Virtual Box
        打开网页:http://enigmaprotector.com/en/downloads.html
        下载文件:enigmavb.exe
        详细连接:http://enigmaprotector.com/assets/files/enigmavb.exe
        安装目录:C:\Program Files (x86)\Enigma Virtual Box
3,查看程序依赖库
        在Qt Creator (Community)中用Realse打开项目setram.exe执行
        打开 odbg201.zip里的ollydbg.exe软件后,用File->Attach菜单 然后选择到程序setram.exe
        执行 View->Executable Modules菜单,找到下列动态链接库:
        C:\Qt\Qt5.4.0\5.4\mingw491_32\bin\icudt53.dll
        C:\Qt\Qt5.4.0\5.4\mingw491_32\bin\icuin53.dll
        C:\Qt\Qt5.4.0\5.4\mingw491_32\bin\icuuc53.dll
        C:\Qt\Qt5.4.0\5.4\mingw491_32\bin\libgcc_s_dw2-1.dll
        C:\Qt\Qt5.4.0\5.4\mingw491_32\bin\libstdc++-6.dll
        C:\Qt\Qt5.4.0\5.4\mingw491_32\bin\libwinpthread-1.dll
        C:\Qt\Qt5.4.0\5.4\mingw491_32\bin\Qt5Core.dll
        C:\Qt\Qt5.4.0\5.4\mingw491_32\bin\Qt5Gui.dll
        C:\Qt\Qt5.4.0\5.4\mingw491_32\bin\Qt5Widgets.dll
        C:\Qt\Qt5.4.0\5.4\mingw491_32\plugins\platforms\qwindows.dll
        C:\Qt\Qt5.4.0\5.4\mingw491_32\plugins\platforms\qminimal.dll
4,打包程序
        打开软件Enigma Virtual Box。新建工程并找到要打包的exe路径及要打包生成的exe的路径
        在下面文件列表中增加上面的每个DLL文件
        icudt53.dll,icuin53.dll,icuuc53.dll
        libgcc_s_dw2-1.dll,libstdc++-6.dll,libwinpthread-1.dll
        Qt5Core.dll ,Qt5Gui.dll,Qt5Widgets.dll
        及文件夹下的platforms\qwindows.dll和platforms\qminimal.dll文件
        然后在右下角“文件选项”中选择上“压缩文件”,       
        最后执行“执行封包”并运行即可退出大功告成。

#64 Qt/MSVC/MINGW/C++/MFC/GTK+/Delphi/BCB » 基于QT 5.8.0 for Android 的 Windows 10 开发环境搭建--缥缈九哥 » 2020-05-09 18:45:37

缥缈九哥
回复: 0

基于QT 5.8.0 for Android 的 Windows 10 开发环境搭建
一、下载软件
1.jdk: jdk-8u121-windows-i586.exe
http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html
http://download.oracle.com/otn-pub/java/jdk/8u121-b13/e9e7ea248e2c4826b92b3f075a80e441/jdk-8u121-windows-i586.exe

2.sdk: android-studio-bundle-145.3537739-windows.exe
https://developer.android.com/studio/index.html
https://dl.google.com/dl/android/studio/install/2.2.3.0/android-studio-bundle-145.3537739-windows.exe
3.qte:  qt-opensource-windows-x86-android-5.8.0-rc_699.exe
http://download.qt.io/development_releases/qt/5.8/5.8.0-rc/
http://download.qt.io/development_releases/qt/5.8/5.8.0-rc/qt-opensource-windows-x86-android-5.8.0-rc_699.exe

4.ndk: android-ndk-r13b-windows-x86.zip
https://developer.android.com/ndk/downloads/index.html
https://dl.google.com/android/repository/android-ndk-r13b-windows-x86.zip

5.ant: apache-ant-1.10.0-bin.zip
http://ant.apache.org/bindownload.cgi
http://mirror.bit.edu.cn/apache//ant/binaries/apache-ant-1.10.0-bin.zip
 
二、安装软件
1,把 jdk-8u121-windows-i586.exe 安装到 C:\Program Files (x86)\Java\jdk1.8.0_121\ 和 C:\Program Files (x86)\Java\jre1.8.0_121 下面;
2,把 android-studio-bundle-145.3537739-windows.exe 安装到 C:\Program Files\Android\Android Studio 和 C:\Users\yuanxihua\AppData\Local\Android\sdk 下面;
3,把 qt-opensource-windows-x86-android-5.8.0-rc_699  的全部组件安装到 C:\Qt\Qt5.8.0 下面;
4,把 android-ndk-r13b-windows-x86.zip 解压到 C:\Qt\android-ndk-r13b 下面;
5,把 apache-ant-1.10.0-bin.zip 解压到 C:\Qt\apache-ant-1.10.0 下面;
三、开发项目
1,配置环境
    打开 C:\Qt\Qt5.8.0\Tools\QtCreator\bin 下面的 qtcreator.exe,在 “工具”->“选项”->“设备”里面选择“andorid”的配置填入上面的软件
JDK、SDK、NDK、ANT的路径:C:\Program Files (x86)\Java\jdk1.8.0_121  和 C:\Users\yuanxihua\AppData\Local\Android\sdk1  和 C:\Qt\android-ndk-r13b
及 C:\Qt\apache-ant-1.10.0\bin\ant.bat
2,建立工程
   A,打开 qtcreator.exe,在“文件”->“新建文件或项目”选择“所有模板”->Application->Qt Widgets Application
然后点击“Choose…”,选择项目路径“D:\works\TEST\qttest”和项目名称“test”,勾选“Android for armeabi-v7a(GCC 4.9 ,Qt 5.8.0)”
和“Desktop Qt 5.8.0 MinGW 32bit”两个模板;
   B,一路直接按下去就建立好测试项目,选择项目里面的“Android for armeabi-v7a(GCC 4.9 ,Qt 5.8.0)”下的构建,然在“构建”菜单下选择
   “选择重新构建项目‘TEST’”进行编译,就会在
“D:\works\TEST\qttest\build-test-Android_for_armeabi_v7a_GCC_4_9_Qt_5_8_0-Release\android-build\bin”下生成“QtApp-debug.apk”
和“QtApp-debug-unaligned.apk”文件;
   C,把生成的APK文件通过数据线下载到安卓手机就能安装测试使用。

#65 Nuvoton N32905/N32926/NUC972/N9H20/N9H26/N9H30 » 基于ARM-MDK+JLINK开发环境的新唐N32905的裸奔调试模板-缥缈九哥移植整理 » 2020-05-09 18:42:12

缥缈九哥
回复: 0

基于ARM-MDK+JLINK开发环境的新唐N32905的裸奔调试模板-缥缈九哥移植整理
   N32905是一个主频高达240MHZ(@2.0V)的ARM926EJ-S核CPU,它内置MJPEG编解码器(VGA 30FPS),CMOS接口(3M),
16Mbitx16 DDR(-20°C~85°C)内存,支持USB2.0 HS从接口,USB1.1 FS主设备口,32通道声音处理单元SPU,
10位麦克风放大ADC, 16位立体声耳机DAC,和TV输出编码器,内置支持FlashLite(FL3.1.7)的2D BitBLT加速器。
支持D1 (720x480)的TV视频输出,支持XVGA(1,024x768)的TFT LCD屏。14X14X1.4MM大小和0.4MM 脚距的S2LQFP-128
小MCP封装。
   它的极高集成度使之仅仅外置一个简单的SPI的FLASH及相关的电源和时钟就可以独立形成最小系统。它可以仅用
双面板设计来降低整机成本及生产工艺难度。它可以用于多媒体处理电子书,学习机,玩具,人机界面,广告指示牌,
WIFI透传模块,IP摄像头,人机界面,二维码识别及机器视觉的应用。
一,N32905的物理寻址空间:
IBR:  0xFFFF_0000 - 0xFFFF_FFFF
保留: 0xFF00_2000 - 0xFFFE_FFFF
SRAM: 0xFF00_0000 - 0xFF00_1FFF
保留: 0xC000_0000 - 0xFEFF_FFFF
APB: 0xB800_0000 - 0xBFFF_FFFF
AHB: 0xB000_0000 - 0xB7FF_FFFF
SSDRAM: 0x8000_0000 - 0xAFFF_FFFF (SDRAM的影射空间)
保留: 0x4000_0000 - 0x7FFF_FFFF
SDRAM: 0x0000_0000 - 0x3FFF_FFFF
二,N32905的内置IBR启动配置:
ND1-0: IBR Boot Mode: 10=Recover; 11=Normal;
ND3-2: Boot crystal : 10=12MHz; 11=27MHz;
others 保留。
三,N32905的内置IBR引导顺序:
1,正常Normal模式串口信息:
Init RTC....OK
DDR size: 32MB
SD Port0 Booting Fail - No/Bad Card Insert
NAND Booting (2K-page 4 Address Cycle) Fail - Not for Booting
SPI Booting Fail - No Check ID
SD Port1 Booting Fail - No/Bad Card Insert
USB Booting
2,修复Recover模式串口信息:
Init RTC....OK
DDR size: 32MB
USB Booting
四,N32905的NANDFLASH配置:
LVDATA[6]:  0=EF((Error Free) NAND;  1=Raw NAND;
LVDATA[5:4]: 0=2K,1=4K,2=8K page size; 3=Ignore NAND;
ND7:   0=4 address cycle;   1=5 address cycle;
ND6:   保留。
ND5-4:   0=SDRAM; 1=mDDR;  2=DDR2;  3=DDR;
五,N32905的物理器件ID:
CHIPID:  0xFA_5C30  ,位于0xB0000000地址
六,9GLoader的简单程序模板
    本程序的串口驱动及头文件移植自新唐的ADS环境的裸奔Non-OS代码包的Loader\NandLoader例子。在建立项目时选择AT91SAM9260及它的启动代码,然后去掉9260的CPU的硬件初始化部分,在MDK的工程配置的执行地址是:0x8000,连接脚本SCT文件用MDK默认产生的,详细可以查看源码包。它能通过JLINK直接下载到CPU里调试,主要是依靠初始化脚本:9G-N32905\cfg\SDRAM.ini进行SDRAM,PLL的初始化及下载AXF文件到SDRAM的8000的执行地址里进行调试。
   附件代码:  http://bbs.21ic.com/forum.php?mod=attachment&aid=MTczNTE2fGZjMTJhNWU3fDE0NjA5NTEyNDJ8NTA1NzExfDU0MjkyOA%3D%3D

( 注:AXF文件是与ELF相兼容的一种调试文件格式,最前面的0-0X33是文件头;接着后面0x34开始就是BIN内容;
再后面是调试信息)

//SDRAM.ini
/******************************************************************************/
/* Dbg_RAM.ini: Initialization Script for Debugging in SDRAM                  */
/******************************************************************************/
/* This file is part of the uVision/ARM development tools.                    */
/* Copyright (c) 2011 Keil Software. All rights reserved.                     */
/* This software may only be used under the terms of a valid, current,        */
/* end user licence from KEIL for a compatible version of KEIL software       */
/* development tools. Nothing else gives you the right to use this software.  */
/******************************************************************************/
DEFINE INT  Entry;
DEFINE LONG GCR_BA;
DEFINE LONG CLK_BA;
DEFINE LONG SDIC_BA;
DEFINE LONG GP_BA;
Entry  = 0x00008000;
GCR_BA  = 0xB0000000;
CLK_BA = 0xB0000200;
SDIC_BA = 0xB0003000;
GP_BA = 0xB8001000;
FUNC void Clock_Setup (void)
{
}
FUNC void SDRAM_Setup(void)
{
_WDWORD(0xb0003000, 0x00130456); // SDOPM Init DDR
_WDWORD(0xb0003030, 0x00001010); // DQSODS
_WDWORD(0xb0003010, 0x00000005); // SDSIZE0
_WDWORD(0xb0003004, 0x00000021); // SDCMD
_WDWORD(0xb0003004, 0x00000023); // SDCMD
_WDWORD(0xb0003004, 0x00000027); // SDCMD
_WDWORD(0xb000301C, 0x00001002); // SDEMR
_WDWORD(0xb0003018, 0x00000122); // SDMR
_WDWORD(0xb0003004, 0x00000027); // SDCMD
_WDWORD(0xb0003004, 0x0000002B); // SDCMD
_WDWORD(0xb0003004, 0x0000002B); // SDCMD
_WDWORD(0xb0003018, 0x00000022); // SDMR
_WDWORD(0xb0003004, 0x00000020); // SDCMD
_WDWORD(0xb0003034, 0x00AAAA00); // CKDQSDS
_WDWORD(0xb0003008, 0x0000805A); // SDREF
_WDWORD(0xb00000A0, 0x00000000); // MISCPCR
_WDWORD(0xb0000224, 0x0000447E); // UPLLCON PLL=192MHz
_WDWORD(0xb000020C, 0x00000018); // CLKDIV0 Divider
_WDWORD(0xb000021C, 0x00000000); // CLKDIV4
_WDWORD(0xb0003028, 0x094E7549); // SDTIME Sdram Timing
    _sleep_(10);
_WDWORD(0xb8001010, 0x00000008); // GPIOB_OMD  PB3=OUTPUT
_WDWORD(0xb8001018, 0x00000008); // GPIOB_DOUT PB3=HIGH
    _sleep_(10);
}
FUNC void Remap (void)
{
}
FUNC void Download (void)
{
    exec("load %L incremental");
}
FUNC void PC_Setup (void)
{
    PC = Entry;
}
FUNC void GoMain (void)
{
    exec("g,main");
}
//Clock_Setup();
SDRAM_Setup();
//Remap();
Download();
PC_Setup();
GoMain();
//main.c文件
#include <stdio.h>
#include "wblib.h"
#define DebugCom 0x100
void Delay(UINT32 k)
{
volatile int j=k*36000;
while(j--);
}
void InitDebugCom(void)
{
WB_UART_T *uart;
//Nornal Speed UART
outp32(REG_GPAFUN, inp32(REG_GPAFUN) | (MF_GPA11 | MF_GPA10));
outp32(REG_APBCLK, inp32(REG_APBCLK) | UART1_CKE);
uart->uiFreq = (((inp32(REG_CHIPCFG)&0xC)==0x8)?12000:27000)*1000; /*Use external clock*/
    uart->uiBaudrate = 115200;
    uart->uiDataBits = WB_DATA_BITS_8;
    uart->uiStopBits = WB_STOP_BITS_1;
    uart->uiParity = WB_PARITY_NONE;
    uart->uiRxTriggerLevel = LEVEL_1_BYTE;
   
/* Reset the TX/RX FIFOs */
outpw(REG_UART_FCR+DebugCom, 0x07);
/* Setup baud rate */
outpw(REG_UART_BAUD+DebugCom, ((0x30<<24)|((uart->uiFreq / uart->uiBaudrate)-2)));
/* Set the modem control register. Set DTR, RTS to output to LOW,
and set INT output pin to normal operating mode */
//outpb(UART_MCR, (WB_DTR_Low | WB_RTS_Low | WB_MODEM_En));
/* Setup parity, data bits, and stop bits */
outpw(REG_UART_LCR+DebugCom,(uart->uiParity | uart->uiDataBits | uart->uiStopBits));
/* Timeout if more than ??? bits xfer time */
outpw(REG_UART_TOR+DebugCom, 0x80+0x20);
/* Setup Fifo trigger level and enable FIFO */
outpw(REG_UART_FCR+DebugCom, uart->uiRxTriggerLevel|0x01);
}
int fputc(int ch, FILE *f)
{
/* Wait until the transmitter buffer is empty */  
while (!(inpw(REG_UART_FSR+DebugCom)&0x400000));
/* Transmit the character */
outpb(REG_UART_THR+DebugCom, ch);
return ch;
}
int fgetc(FILE *f)
{
while((inpw(REG_UART_ISR+DebugCom)&0x01)==0);
return(inpb(REG_UART_RBR+DebugCom));
}
int main(void)
{
int i=0;
InitDebugCom();
printf("\n\r\n\r");
printf("*** 9G-N32905 V1.00 Build by yuanxihua@21cn.com on ("__DATE__ " - " __TIME__ ")\n\r");
printf("*** 9G-N32905 V1.00 Running ...\n\r\n\r");
outp32(REG_GPIOC_OMD,0x0000FFFF);
outp32(REG_GPIOE_OMD,0x0000FFFF);
while(1)
{
  printf("run times %d\n\r",i++);
  outp32(REG_GPIOC_DOUT,0x0000FFFF);
  outp32(REG_GPIOE_DOUT,0x0000FFFF);
  Delay(500);
  outp32(REG_GPIOC_DOUT,0x00000000);
  outp32(REG_GPIOE_DOUT,0x00000000);
  Delay(500);   
}
}

#66 Cortex M0/M3/M4/M7 » 基于新唐M0516的MDK+GCC的编译环境建立与LOOK应用开发--缥缈九哥 » 2020-05-09 18:39:24

缥缈九哥
回复: 6

基于新唐M0516的MDK+GCC的编译环境建立与LOOK应用开发
一,下载安装MDK+GCC编译环境
1,从KEIL主页上下载MDK471A的:http://www.keil.com/fid/edz9p7w1 ... es/eval/mdk471a.exe
        并且默认安装到C盘的:C:\Keil,自行和谐处理。
2,从https://sourcery.mentor.com/GNUToolchain/release2449上面下载Sourcery CodeBench Lite Edition for ARM EABI
        https://sourcery.mentor.com/GNUT ... 3-arm-none-eabi.exe
        并且默认安装到C:\Program Files\CodeSourcery\Sourcery_CodeBench_Lite_for_ARM_EABI
        修改XP下的系统环境变量最前添加:C:\Program Files\CodeSourcery\Sourcery_CodeBench_Lite_for_ARM_EABI\bin;
       
3,在新唐主页上下载安装NU-LINK驱动和ICP软件,并安装到C:\Keil里面。
4,在新唐主页上下载数据手册,BSP包文件。
二,建立“Keil uVision4”工程项目
1,在“D:\works\9G-CM0\”下建立“9G-LOOK”目录,再在“9G-LOOK”目录下建立“look”“src”“inc”“prj”目录;
        在“prj”下再建立“debug\obj”“debug\lst”“release\obj”“release\lst”目录;
       
2,打开桌面的“Keil uVision4”,点开“project”->“New uVision project”选择路径到“D:\works\9G-CM0\9G-LOOK\prj”
        建立“9g-look”工程;
       
3,在接着的“select a CPU Data Base File”上选择“NuMicro Cortex M0 Database”数据库;在里面的“Nuvoton”下拉中选择
        器件中选择“M0516LBN”后点击OK并选择“否”禁止拷贝启动代码文件;
       
4,在“Keil uVision4”窗口的左面的“project”窗口里的“Target 1”改成成“debug”,下面的“Source Group 1”改名成“look”;
        并且在“project”窗口里的“debug”上右击“Add Group”建立一个空文件夹,并改名成“src”;
       
5,点击“Keil uVision4”窗口菜单的“Targets Options”,打开项目配置窗口的“Output”,点开“Select Folder for Objects...”
        选择到“D:\works\9G-CM0\9G-LOOK\prj\debug\obj\”并勾选上“Create HEX File”;
6,        打开项目配置窗口的“Listing”,点开“Select Folder for Listing...”选择到“D:\works\9G-CM0\9G-LOOK\prj\debug\lst\”;并且
    把下面的所有选项全部勾上;
   
7,在项目配置窗口的“User”窗口的编译成功能运行的命令第一行,第二行勾选并分别填入命令:
        “arm-none-eabi-objcopy.exe -O binary -j .text .\debug\obj\!L.elf  .\debug\obj\!L.bin”
        “arm-none-eabi-size.exe  !L.elf”
8,在项目配置窗口“CC”窗口,填上宏定义define:“SEMIHOSTING”,包含路径“..\src;..\inc;..\look\include”
        去掉“enable APCS...”和        “Support Calls Between ....”选择项并勾选上“Compile Thumb code”和真入编译器编译控制参数
        “-pipe -ffunction-sections -fdata-sections -gstrict-dwarf -finline-limit=100000000”
       
       
9,在项目配置窗口的“Linker”窗口里,勾选择上不用标准启动文件和库文件,填入连接脚本:“.\m051.ld”,LOOK的路径
        “..\look\lib”        和连接控制参数“-Wl,--relax -Wl,--gc-sections -Wl,-z -Wl,max-page-size=0”
       
10,在项目配置窗口的“Debug”和“Utilities”窗口里都选择上仿真下载器“Nuvoton Nu-Link Debugger”并勾选择上“Run to main{}”
        和“Update Target Before Debugging”。
11,在“project”->“Manage”->“Compoments...”的“Folders..”里面选择GCC做编译器前缀是“arm-none-eabi-”
        编译器的路径为:“C:\Program Files\CodeSourcery\Sourcery_CodeBench_Lite_for_ARM_EABI\”
12,在“project”->“Manage”->“Compoments...”的“Project...”里面增加一个“release”版本的工程,在这个工程“Targets Options”的
        “Output”和“Listing”指定目录到“release\obj”“release\lst”目录;“CC”里的宏定义“SEMIHOSTING”去掉;
13,右击在“Keil uVision4”窗口的左面的“project”下的“src”文件夹,选择“options”里的“CC”添加上编译选项
        “-std=c++11 -fno-rtti -fno-exceptions -Wno-pmf-conversions”
三,组织“Keil uVision4”工程项目
1,把“j.y.lee@yeah.net”老师的“look”里的“include”“lib”“look-rm.chm”全部复制到“D:\works\9G-CM0\9G-LOOK\look”        目录;
        把“.\m051.ld”复制到“D:\works\9G-CM0\9G-LOOK\prj”下,把“numicro”放到“INC”目录;
2,把“idle.cpp”“idle.h”“init.cpp”“scheduler.cpp”“systick.cpp”“vector.cpp”“semi.cpp”“semi.h”全部复制到
        “D:\works\9G-CM0\9G-LOOK\src”目录;
3,把文件“look.h”和“m0516lan.h”放到目录“D:\works\9G-CM0\9G-LOOK\inc”中,并且把上面的CPP文件添加到工程“Project”
        下面的“Debug”下的“src”中,把“look.h”“attribute.h”“sfr”“m0516lan.h”放到“D:\works\9G-CM0\9G-LOOK\inc”中。
       
4,把“redapricot”和“utils”文件夹及“sfr”文件复制到“D:\works\9G-CM0\9G-LOOK\inc”中;在D:\works\9G-CM0\9G-LOOK\src
建立“led.h”和“led.cpp”文件,编写LED闪烁代码并添加到项目工程的src中。
四,编译及运行工程项目
1,按“F7”进去项目工程的编译,“CTRL+F5”进行DEBUG下载;“F5”全速运行项目即可看到LED在秒闪烁。
2,项目工程源码程序,请到下面网址上下载:http://bbs.21ic.com/icview-554086-1-1.html

#67 Cortex M0/M3/M4/M7 » 基于新唐MINI51的红外接收解码方案--缥缈九哥 » 2020-05-09 18:38:23

缥缈九哥
回复: 0
/******************************************************************************
* @file     ir.c
* @brief    The Driver code for VS1838A with MINI54FDE
* @version  1.0.0
* @date     22, August, 2014
*
* @note
* Copyright (C) 2000-2014 PM9GZY by yuanxihua@21cn.com. All rights reserved.
******************************************************************************/
#include <stdio.h>
#include "Mini51Series.h"
/*
    红外线编码是数据传输和家用电器遥控常用的一种通讯方法,
其实质是一种脉宽调制的串行通讯。
    家电遥控中常用的红外线编码电路有μPD6121G型HT622型和7461型等。
μPD6121G遥控器的红外遥控系统的编码格式
    二进制“0”由0.56ms的间隔加0.565ms的脉冲表示;
    二进制“1”由0.56ms的间隔加1.685ms的脉冲表示。
每次发送的32位二进制码可分成两部分,其中
        前16位是遥控器辨识码,主要用于区别不同遥控器,
        后16位是操作码。这两个部分的后8位都是前8位的反码,用作数据校验。
每帧数据以9ms的间隔加4.5ms的脉冲作为数据头header信号。
    当键盘按下长达108ms时,发射端开始发送连续信号,与单次发送一样,
只是数据头header信号是由9ms的间隔加2.5ms的脉冲组成的。
*/
/*
_________________________________________________
|        MINI54FDE                                                LED                        |
|                                                                                                |
|        P25                                        <---                VS1838A                |
|        P24                                        --->                RED-LED                |
|_______________________________________________|
*/
#pragma anon_unions
#define TIME_INTERRUPT_PERIOD_US        128                //定时中断时间,用于计算下降沿到下降沿之间时间,也就是一个脉冲+间隙的时间
#define TIME_INFRARED_HEAD_US                13500        //数据头的时间:TH=9+4.5=13.5ms
#define TIME_INFRARED_REPEAT_US                11500        //当键盘按下长达108ms时,发送连续信号的数据头的时间:TH=9+2.5=11.5ms
#define TIME_INFRARED_ZERO_US                1125        //数据“0”的时间:T0=0.565+0.56=1.125ms
#define TIME_INFRARED_ONE_US                2245        //数据“1”的时间:T1=1.685+0.56=2.245ms
typedef enum  {IDLE=1,HEAD,DATA} irstatus_t;
typedef union {uint32_t data;struct {uint8_t data0;uint8_t data1;uint16_t address;};}irdata_t;
irdata_t ir;
uint32_t irticks=0,ircount=0,ledcount=0;
irstatus_t irwork=IDLE;
uint8_t disp_flag=0;
// The Timer1 default IRQ, declared in startup_Mini51.s.
void TMR1_IRQHandler(void)
{
        irticks++;ledcount++;
        TIMER_ClearIntFlag(TIMER1);
}
// The Port2/Port3/Port4 default IRQ, declared in startup_Mini51.s.
void GPIO234_IRQHandler(void)
{
        uint8_t irdata;
    if (P2->ISRC & BIT5)
    {    /* To check if P2.5 interrupt occurred */
                switch(irwork)
                {
                        case IDLE: irwork=HEAD;
                                break;
                        case HEAD: irwork=(irticks>((TIME_INFRARED_HEAD_US+TIME_INFRARED_REPEAT_US)/2)/TIME_INTERRUPT_PERIOD_US)?DATA:IDLE;
                                ir.data=0;ircount=0;
                                break;
                        case DATA: irdata=(irticks>((TIME_INFRARED_ZERO_US+TIME_INFRARED_ONE_US   )/2)/TIME_INTERRUPT_PERIOD_US)?1:0;
                                ir.data<<=1;ir.data|=irdata;ircount++;
                                if(ircount>=32){irwork=IDLE;disp_flag=1;}
                                break;
                }       
                irticks=0;        P2->ISRC = BIT5;
    }else
    {   /* Un-expected interrupt. Just clear all PORT2, PORT3 and PORT4 interrupts */
        P2->ISRC = P2->ISRC;        P3->ISRC = P3->ISRC;        P4->ISRC = P4->ISRC;
        printf("Un-expected interrupts. \n\r");
    }
}
void IR_test(void)
{
    /*Configure P24 for LED control */
    GPIO_SetMode(P2, BIT4, GPIO_PMD_OUTPUT);
       
        /*  Configure P2.5 as Quasi-bidirection mode and enable interrupt by falling edge trigger */
    GPIO_SetMode(P2, BIT5, GPIO_PMD_QUASI);
    GPIO_EnableInt(P2, 5, GPIO_INT_FALLING);
    NVIC_EnableIRQ(GPIO234_IRQn);
       
        // Enable IP clock
        CLK_EnableModuleClock(TMR1_MODULE);       
    // Select Timer 1 clock source from internal 22.1184MHz RC clock.
        CLK_SetModuleClock(TMR1_MODULE,CLK_CLKSEL1_TMR1_S_IRC22M,1);
        // configure timer to operate in specified mode.
        TIMER_Open(TIMER1, TIMER_PERIODIC_MODE, 7812);        //7.8125K = 0.128MS = 128US
        // start Timer counting
        TIMER_Start(TIMER1);
        // enable the Timer time-out interrupt function.
        TIMER_EnableInt(TIMER1);
    // Enable timer interrupt
    NVIC_EnableIRQ(TMR1_IRQn);
       
        while(1)
        {
                if(disp_flag)
                {
                        printf("ir.data=0x%x, ADDR=%04x DATA1=%02x /DATA1=%02x DATA0=%02x \n\r",
                                        ir.data,ir.address,ir.data1,0xff-ir.data1,ir.data0);
                        if((0xff-ir.data0)==ir.data1){P24^=1;}
                        disp_flag=0;
                }
        }
}

#68 Cortex M0/M3/M4/M7 » 基于M0516的TM1812的SPI驱动代码--缥缈九哥 » 2020-05-09 18:36:42

缥缈九哥
回复: 0

//SPI的时钟定为2.5MHZ,也就是400NS,一个数据位用3位SPI波形来表示;
//那么就把一个数据字节扩展成了24位的SPI波形字长;
//把逻辑0转化成二进制100就是0x04,就是高400nS,低800nS;
//把逻辑1转化成二进制110就是0x06,就是高800nS,低400nS;
//这样就能用SPI的MOSI发数据来驱动TM1812的DIN。
源码:

/*---------------------------------------------------------------------------------------------------------*/
/* @file     tm1812.c                                                                                                                                                                           */
/* @version  V1.00                                                                                                                                                                                   */
/* $Date:          15/07/01 11:44a $                                                                                                                                                           */
/* @brief    M051 Series UART for M35 GPRS Sample Code                                                                                                      */
/* Copyright(c) PM9GZY Technology Corp. yuanxihua@21cn.com. All rights reserved.                                     */
/*                                                                                                         */
/*---------------------------------------------------------------------------------------------------------*/
#include "main.h"
/*   M0516LBN MOSI -->  TM1812  DIN   */
/*
逻辑0        高电平时间        350-450ns        低电平时间        800-900ns
逻辑1        高电平时间        700-999ns        低电平时间        250-550ns
位逻辑  低电平时间        8-24us
逻辑0        高400NS        低800NS
逻辑1        高800NS 低400NS
复位        低2000NS
*/
/* Function prototype declaration */
void SPI0_Init(void);
void spi0_write(uint32_t word)
{
//        while(SPI_GET_TX_FIFO_FULL_FLAG(SPI0));
        /* Write to TX register */
        SPI_WRITE_TX0(SPI0, word);
        /* Trigger SPI data transfer */
        SPI_TRIGGER(SPI0);
        /* Check SPI0 busy status */
        while(SPI_IS_BUSY(SPI0));
        /* Read received data */
//        tmp = SPI_READ_RX0(SPI0);tmp=tmp;
}
//SPI的时钟定为2.5MHZ,也就是400NS,一个数据位用3位SPI波形来表示;
//那么就把一个数据字节扩展成了24位的SPI波形字长;
//把逻辑0转化成二进制100就是0x04,就是高400nS,低800nS;
//把逻辑1转化成二进制110就是0x06,就是高800nS,低400nS;
//这样就能用SPI的MOSI发数据来驱动TM1812的DIN。
void tm1812_write_byte(uint8_t byte)
{
        uint32_t tmp,data=0;
        for(uint8_t i=0;i<8;i++){tmp=(byte&1)?0x06:0x04;data|=tmp<<(i*3);byte>>=1;}
        spi0_write(data);
}
void tm1812_display_lamp(color_t *led)
{
        for(uint8_t i=0;i<24;i++)
        {
                tm1812_write_byte(led.red);
                tm1812_write_byte(led.green);
                tm1812_write_byte(led.blue);
        }
        CLK_SysTickDelay(24); //更新显示,复位时间24uS
}
void tm1812_display_all(color_t *color)
{
        color_t led[24];for(uint8_t i=0;i<24;i++){led=*color;}
        tm1812_display_lamp((color_t*)led);
}
void tm1812_display_off(void){uint32_t color =0;tm1812_display_all((color_t *)&color);}
void tm1812_display_key(uint8_t key_value,color_t *color)
{
        color_t led[24];memset((void *)&led[0],0,sizeof(led));
        led[0]=*color;for(uint8_t i=0;i<key_value;i++){led[8+i]=*color;}
        tm1812_display_lamp((color_t*)led);
}
void spi0_test(void)
{
        uint32_t i;
        for(i=0;i<254;i++){uint32_t color=i<<16;tm1812_display_all((color_t *)&color);CLK_SysTickDelayMs(4);}
        while(i--)        {uint32_t color=i<<16;tm1812_display_all((color_t *)&color);CLK_SysTickDelayMs(4);}
        for(i=0;i<254;i++){uint32_t color=i<< 8;tm1812_display_all((color_t *)&color);CLK_SysTickDelayMs(4);}
        while(i--)        {uint32_t color=i<< 8;tm1812_display_all((color_t *)&color);CLK_SysTickDelayMs(4);}
        for(i=0;i<254;i++){uint32_t color=i<< 0;tm1812_display_all((color_t *)&color);CLK_SysTickDelayMs(4);}
        while(i--)        {uint32_t color=i<< 0;tm1812_display_all((color_t *)&color);CLK_SysTickDelayMs(4);}
        tm1812_display_off();CLK_SysTickDelayMs(200);
}
void SPI0_Init(void)
{
        /* Select HCLK as the clock source of SPI0 */
    CLK_SetModuleClock(SPI0_MODULE, CLK_CLKSEL1_SPI0_S_HCLK, MODULE_NoMsk);
    /* Enable SPI0 peripheral clock */
    CLK_EnableModuleClock(SPI0_MODULE);
       
        /* Setup SPI0 multi-function pins */
       
        /* Set P1 multi-function pins for SPI0  */
        SYS->P1_MFP = (SYS->P1_MFP & (~(SYS_MFP_P14_Msk | SYS_MFP_P15_Msk | SYS_MFP_P16_Msk | SYS_MFP_P17_Msk)))
        | (/*SYS_MFP_P14_SPISS0 |*/ SYS_MFP_P15_MOSI_0 /*| SYS_MFP_P16_MISO_0 | SYS_MFP_P17_SPICLK0*/);
       
        /* Set P1。3 pins for GPIO */
        SYS->P1_MFP = (SYS->P1_MFP & (~(SYS_MFP_P13_Msk))) | (SYS_MFP_P13_TXD1);
        /* Configure P1.3 as Input mode */
    GPIO_SetMode(P1, BIT3, GPIO_PMD_INPUT);
    /*---------------------------------------------------------------------------------------------------------*/
    /* Init SPI                                                                                                */
    /*---------------------------------------------------------------------------------------------------------*/
    /* Configure as a master, clock idle low, 24-bit transaction, drive output on falling clock edge and latch input on rising edge. */
    /* Set IP clock divider. SPI clock rate = 2.5MHz */
    SPI_Open(SPI0, SPI_MASTER, SPI_MODE_0, 24, 2500000);
    /* Enable the automatic hardware slave select function. Select the SS pin and configure as low-active. */
    SPI_EnableAutoSS(SPI0, SPI_SS, SPI_SS_ACTIVE_LOW);
}

//完毕

#69 Cortex M0/M3/M4/M7 » 基于NANO120的16位EBI总线的SSD1963的480X272驱动--缥缈九哥 » 2020-05-09 18:35:23

缥缈九哥
回复: 0

最近做个项目,用到ARMJISHU公司的神舟III号4.3寸液晶屏,用NANO120KE3BN驱动起来了。CPU的PLL是96M,主频超到了48M。特地发出来抛砖引玉。

源码:

/******************************************************************************
* @file     ssd1963.c
* @brief    The Driver code for 480*272 16 Color LCD with NANO120KE3BN
* @version  1.0.0
* @date     05, December, 2013
*
* @note
* Copyright (C) 2000-2013 PM9GZY by yuanxihua@21cn.com. All rights reserved.
******************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include <stdio.h>
#include "nano1xx.h"
#include "nano1xx_gpio.h"
#include "nano1xx_ebi.h"
#include "stdlib.h"
#include "core_cmInstr.h"
#include "rfid.h"
/*
_________________________________________________
| NANO120KE3BN     SSD1963  |
|            |
| EBIAD0- EBIAD15  <--->  DB0-DB15 |
| EBIWR PA10  ---->  WR#   |
| EBIRD PA11  ---->  RD#   |
| EBICS PB7   ---->  CS#   |
| PB6  EBIALE  ---->  D/C#  |
| PA8  EBIPA8  ---->  RESET#  |
| PA9  EBIPA9  ---->  LEDA  |
|_______________________________________________|
*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define LCD_LEDA  GPIOA, 9  /* PA9=High,BackLight ON; Low,BackLight OFF */
#define LCD_RESET  GPIOA, 8  /* PA8=Low,LCD Reset;PA8=High,LCD Working   */
#define LCD_DCMD  GPIOB, 6  /* PB6=High,DATA mode; PB6=Low,COMMAND mode */
#define LCD_RESET_DELAY 100    /* LCD_RESET=Low,LCD_RESET_DELAY>=100us  */
#define BLACK         0x0000        /* 黑色:  0  , 0  , 0   */        
#define NAVY          0x000F         /* 深蓝色: 0  , 0  , 128   */        
#define DGREEN        0x03E0          /* 深绿色: 0  , 128, 0     */      
#define DCYAN         0x03EF         /* 深青色: 0  , 128, 128   */      
#define MAROON        0x7800          /* 深红色: 128, 0  , 0     */      
#define PURPLE       0x780F          /* 紫色:  128, 0  , 128   */        
#define OLIVE         0x7BE0         /* 橄榄绿: 128, 128, 0     */     
#define LGRAY         0xC618         /* 灰白色: 192, 192, 192   */      
#define DGRAY         0x7BEF          /* 深灰色: 128, 128, 128   */      
#define BLUE          0x001F          /* 蓝色:  0  , 0  , 255   */         
#define GREEN         0x07E0          /* 绿色:  0  , 255, 0     */         
#define CYAN          0x07FF          /* 青色:  0  , 255, 255   */         
#define RED           0xF800          /* 红色:  255, 0  , 0     */         
#define MAGENTA       0xF81F          /* 品红:  255, 0  , 255   */        
#define YELLOW        0xFFE0         /* 黄色:  255, 255, 0     */      
#define WHITE         0xFFFF          /* 白色:  255, 255, 255  */
#define SSD1963_HDP  0xDF01   /* HDP=479=0x01DF  */
#define SSD1963_HT  0x1302   /* HT =531=0x0213  */
#define SSD1963_HPS  0x2B00   /* HPS=43 =0x002B */
#define SSD1963_LPS  0x0800   /* LPS=8  =0x0008 */
#define SSD1963_HPW  10    /* HPW=10 =0x0A  */
#define SSD1963_VDP  0x0F01   /* VDP=271=0x010F */
#define SSD1963_VT  0x2001   /* VT =288=0x0120  */
#define SSD1963_VPS  0x0C00   /* VPS=12 =0x000C */
#define SSD1963_FPS  0x0100   /* FPS=1  =0x0001 */
#define SSD1963_VPW  10    /* VPW=10 =0x0A  */
/* Private macro -------------------------------------------------------------*/
/*  Command      Hex Code Description */
#define SSD1963_nop      0x00 /* No operation */
#define SSD1963_soft_reset     0x01 /* Software Reset */
#define SSD1963_get_power_mode    0x0A /* Get the current power mode */
#define SSD1963_get_address_mode   0x0B /* Get the frame buffer to the display panel read order */
#define SSD1963_Reserved0c     0x0C /* Reserved */
#define SSD1963_get_display_mode   0x0D /* The SSD1963 returns the Display Image Mode. */
#define SSD1963_get_tear_effect_status  0x0E /* Get the Tear Effect status */
#define SSD1963_Reserved0f     0x0F /* Reserved */
#define SSD1963_enter_sleep_mode   0x10 /* Turn off the panel. This command will pull low the GPIO0. If GPIO0 is configured as normal GPIO or LCD miscellaneous signal with command set_gpio_conf, this command will be ignored. */
#define SSD1963_exit_sleep_mode   0x11 /* Turn on the panel. This command will pull high the GPIO0. If GPIO0 is configured as normal GPIO or LCD miscellaneous signal with command set_gpio_conf, this command will be ignored. */
#define SSD1963_enter_partial_mode   0x12 /* Part of the display area is used for image display. */
#define SSD1963_enter_normal_mode   0x13 /* The whole display area is used for image display. */
#define SSD1963_exit_invert_mode   0x20 /* Displayed image colors are not inverted. */
#define SSD1963_enter_invert_mode   0x21 /* Displayed image colors are inverted. */
#define SSD1963_set_gamma_curve   0x26 /* Selects the gamma curve used by the display panel. */
#define SSD1963_set_display_off   0x28 /* Blanks the display panel */
#define SSD1963_set_display_on    0x29 /* Show the image on the display panel */
#define SSD1963_set_column_address   0x2A /* Set the column address */
#define SSD1963_set_page_address   0x2B /* Set the page address */
#define SSD1963_write_memory_start   0x2C /* Transfer image information from the host processor interface to the SSD1963 starting at the location provided by set_column_address and set_page_address  */
#define SSD1963_read_memory_start   0x2E /* Transfer image data from the SSD1963 to the host processor interface starting at the location provided by set_column_address and set_page_address  */
#define SSD1963_set_partial_area   0x30 /* Defines the partial display area on the display panel */
#define SSD1963_set_scroll_area   0x33 /* Defines the vertical scrolling and fixed area on display area */
#define SSD1963_set_tear_off    0x34 /* Synchronization information is not sent from the SSD1963 to the host processor */
#define SSD1963_set_tear_on    0x35 /* Synchronization information is sent from the SSD1963 to the host processor at the start of VFP */
#define SSD1963_set_address_mode   0x36 /* Set the read order from frame buffer to the display panel */
#define SSD1963_set_scroll_start   0x37 /* Defines the vertical scrolling starting point */
#define SSD1963_exit_idle_mode    0x38 /* Full color depth is used for the display panel */
#define SSD1963_enter_idle_mode   0x39 /* Reduce color depth is used on the display panel. */
#define SSD1963_Reserved3a     0x3A /* Reserved */
#define SSD1963_write_memory_continue  0x3C /* Transfer image information from the host processor interface to the SSD1963 from the last written location */
#define SSD1963_read_memory_continue  0x3E /* Read image data from the SSD1963 continuing after the last read_memory_continue or read_memory_start */
#define SSD1963_set_tear_scanline   0x44 /* Synchronization information is sent from the SSD1963 to the host processor when the display panel refresh reaches the provided scanline  */
#define SSD1963_get_scanline    0x45 /* Get the current scan line */
#define SSD1963_read_ddb     0xA1 /* Read the DDB from the provided location */
#define SSD1963_Reserveda8     0xA8 /* Reserved */
#define SSD1963_set_lcd_mode   0xB0 /* Set the LCD panel mode and resolution */
#define SSD1963_get_lcd_mode    0xB1 /* Get the current LCD panel mode, pad strength and resolution */
#define SSD1963_set_hori_period   0xB4 /* Set front porch */
#define SSD1963_get_hori_period   0xB5 /* Get current front porch settings */
#define SSD1963_set_vert_period   0xB6 /* Set the vertical blanking interval between last scan line and next LFRAME pulse */
#define SSD1963_get_vert_period   0xB7 /* Set the vertical blanking interval between last scan line and next LFRAME pulse */
#define SSD1963_set_gpio_conf    0xB8 /* Set the GPIO configuration. If the GPIO is not used for LCD, set the direction. Otherwise, they are toggled with LCD signals. */
#define SSD1963_get_gpio_conf    0xB9 /* Get the current GPIO configuration */
#define SSD1963_set_gpio_value    0xBA /* Set GPIO value for GPIO configured as output  */
#define SSD1963_get_gpio_status   0xBB /* Read current GPIO status. If the individual GPIO was configured as input, the value is the status of the corresponding pin. Otherwise, it is the programmed value. */
#define SSD1963_set_post_proc    0xBC /* Set the image post processor */
#define SSD1963_get_post_proc    0xBD /* Set the image post processor */
#define SSD1963_set_pwm_conf    0xBE /* Set the image post processor */
#define SSD1963_get_pwm_conf    0xBF /* Set the image post processor */
#define SSD1963_set_lcd_gen0    0xC0 /* Set the rise, fall, period and toggling properties of LCD signal generator 0 */
#define SSD1963_get_lcd_gen0    0xC1 /* Get the current settings of LCD signal generator 0 */
#define SSD1963_set_lcd_gen1    0xC2 /* Set the rise, fall, period and toggling properties of LCD signal generator 1 */
#define SSD1963_get_lcd_gen1    0xC3 /* Get the current settings of LCD signal generator 1 */
#define SSD1963_set_lcd_gen2    0xC4 /* Set the rise, fall, period and toggling properties of LCD signal generator 2 */
#define SSD1963_get_lcd_gen2    0xC5 /* Get the current settings of LCD signal generator 2 */
#define SSD1963_set_lcd_gen3    0xC6 /* Set the rise, fall, period and toggling properties of LCD signal generator 3 */
#define SSD1963_get_lcd_gen3    0xC7 /* Get the current settings of LCD signal generator 3  */
#define SSD1963_set_gpio0_rop    0xC8 /* Set the GPIO0 with respect to the LCD signal generators using ROP operation. No effect if the GPIO0 is configured as general GPIO. */
#define SSD1963_get_gpio0_rop    0xC9 /* Get the GPIO0 properties with respect to the LCD signal generators. */
#define SSD1963_set_gpio1_rop    0xCA /* Set the GPIO1 with respect to the LCD signal generators using ROP operation. No effect if the GPIO1 is configured as general GPIO. */
#define SSD1963_get_gpio1_rop    0xCB /* Get the GPIO1 properties with respect to the LCD signal generators.  */
#define SSD1963_set_gpio2_rop    0xCC /* Set the GPIO2 with respect to the LCD signal generators using ROP operation. No effect if the GPIO2 is configured as general GPIO. */
#define SSD1963_get_gpio2_rop    0xCD /* Get the GPIO2 properties with respect to the LCD signal generators. */
#define SSD1963_set_gpio3_rop    0xCE /* Set the GPIO3 with respect to the LCD signal generators using ROP operation. No effect if the GPIO3 is configured as general GPIO. */
#define SSD1963_get_gpio3_rop    0xCF /* Get the GPIO3 properties with respect to the LCD signal generators. */
#define SSD1963_set_dbc_conf    0xD0 /* Set the dynamic back light configuration 0xD1 get_dbc_conf Get the current dynamic back light configuration  */
#define SSD1963_set_dbc_th     0xD4 /* Set the threshold for each level of power saving */
#define SSD1963_get_dbc_th     0xD5 /* Get the threshold for each level of power saving */
#define SSD1963_set_pll     0xE0 /* Start the PLL. Before the start, the system was operated with the crystal oscillator or clock input */
#define SSD1963_set_pll_mn     0xE2 /* Set the PLL */
#define SSD1963_get_pll_mn     0xE3 /* Get the PLL settings */
#define SSD1963_get_pll_status    0xE4 /* Get the current PLL status */
#define SSD1963_set_deep_sleep    0xE5 /* Set deep sleep mode */
#define SSD1963_set_lshift_freq   0xE6 /* Set the LSHIFT (pixel clock) frequency */
#define SSD1963_get_lshift_freq   0xE7 /* Get current LSHIFT (pixel clock) frequency setting */
#define SSD1963_Reservede8     0xE8 /* Reserved */
#define SSD1963_Reservede9     0xE9 /* Reserved */
#define SSD1963_set_pixel_data_interface 0xF0 /* Set the pixel data format of the parallel host processor interface */
#define SSD1963_get_pixel_data_interface 0xF1 /* Get the current pixel data format settings */
#define SSD1963_Reservedff     0xFF /* Reserved */
/* Private variables ---------------------------------------------------------*/
void SSD1963_Fill(uint16_t color);
extern void SYS_Delay(uint32_t us);
void Delay_ms(uint32_t ms)
{
for(uint32_t i=0;i<ms;i++){SYS_Delay(1000);}
}
// Enable EBI function with 16-bit data width
void NANOEBI_Init(void)
{
EBI_TIMING_T sEBITiming;
UNLOCKREG();
/* Enable EBI clock  */
    CLK->AHBCLK |= CLK_AHBCLK_EBI_EN;
/* EBI function enable */
EBI->EBICON |= EBI_EBICON_ExtEN;
EBI->EBICON |= EBI_EBICON_ExtBW16;
// Enable EBIAD15-0, GPIOPA9-8
GCR->PA_L_MFP = (GCR->PA_L_MFP & 0x0000000f) | 0x22222220; //PA7_MFP-PA1_MFP = EBI AD[6]-EBI AD[12]
GCR->PA_H_MFP = (GCR->PA_H_MFP & 0xf0000000) | 0x02222200; //PA14_MFP-PA12_MFP = EBI AD[15]-EBI AD[13] PA11_MFP-PA10_MFP = EBIWR-EBIRD PA9_MFP-PA8_MFP = PA9-PA8
GCR->PB_L_MFP = (GCR->PB_L_MFP & 0x00ffffff) | 0x20000000; //PB7_MFP-PB6_MFP = EBICS-PB6
GCR->PB_H_MFP = (GCR->PB_H_MFP & 0xff00ffff) | 0x00220000; //PB13_MFP-PB12_MFP = EBI AD[1]-EBI AD[0]
GCR->PC_L_MFP = (GCR->PC_L_MFP & 0x00ffffff) | 0x22000000; //PC15_MFP-PC14_MFP = EBI AD[3]-EBI AD[2]
GCR->PC_H_MFP = (GCR->PC_H_MFP & 0x00ffffff) | 0x22000000; //PC7_MFP-PC6_MFP = EBI AD[5]-EBI AD[4]
sEBITiming.eMCLKDIV = E_EBI_MCLKDIV_1;  //OK!!! 480NS 2.083MHZ
  sEBITiming.u8ExttALE=sEBITiming.u8ExtIR2R=sEBITiming.u8ExtIR2W = 0;
sEBITiming.u8ExtIW2X=sEBITiming.u8ExttAHD=sEBITiming.u8ExttACC = 0;
EBI_SetBusTiming(sEBITiming);
*(volatile uint16_t*)EBI_BASE_ADDR=0xFFFF;  //Set D0-D15 to HIGH
GPIO_Open(GPIOA, GPIO_PMD_PMD8_OUTPUT, GPIO_PMD_PMD8_MASK);
GPIO_Open(GPIOA, GPIO_PMD_PMD9_OUTPUT, GPIO_PMD_PMD9_MASK);
GPIO_Open(GPIOB, GPIO_PMD_PMD6_OUTPUT, GPIO_PMD_PMD6_MASK);
GPIO_SetBit(LCD_LEDA);      //PA9=High,BackLight ON; Low,BackLight OFF
GPIO_SetBit(LCD_DCMD);      //PB6=High,DATA mode; PB6=Low,COMMAND mode
GPIO_SetBit(LCD_RESET);      //PA8=Low,LCD Reset;PA8=High,LCD Working
SYS_Delay(LCD_RESET_DELAY);
GPIO_ClrBit(LCD_RESET);
SYS_Delay(LCD_RESET_DELAY);
GPIO_SetBit(LCD_RESET);
// LOCKREG();
}
static void EBI_test(void) {while(1) {*(volatile uint16_t*)EBI_BASE_ADDR=0x5555;*(volatile uint16_t*)EBI_BASE_ADDR=0xAAAA;}}
static __INLINE void SSD1963_WrPAR(uint8_t *data, uint8_t len){while(len--){EBI_WRITE_DATA16(0, *data++);}}
static __INLINE void SSD1963_WrCMD(uint8_t cmd, uint8_t *data, uint8_t len){GPIO_ClrBit(LCD_DCMD);EBI_WRITE_DATA16(0, cmd);GPIO_SetBit(LCD_DCMD);SSD1963_WrPAR(data, len);}
static __INLINE void SSD1963_WrRAM(uint16_t *data, uint32_t len){while(len--){EBI_WRITE_DATA16(0, *data++);}}
void SSD1963_Init(void)
{
uint32_t Parameter;
Parameter=0x04021d;   //PLL multiplier, set PLL clock to 120M N=0x36 for 6.5M, 0x23 for 10M crystal
SSD1963_WrCMD(SSD1963_set_pll_mn,(uint8_t*)&Parameter, 3);
Parameter=0x01;    //Enable PLL
SSD1963_WrCMD(SSD1963_set_pll,(uint8_t*)&Parameter, 1);
Delay_ms(1);
Parameter=0x03;    //Use PLL output as system clock
SSD1963_WrCMD(SSD1963_set_pll,(uint8_t*)&Parameter, 1);
Delay_ms(5);
SSD1963_WrCMD(SSD1963_soft_reset,(uint8_t*)&Parameter, 0); //software reset
Delay_ms(5);
Parameter=0x16D900;   //PLL setting for PCLK, depends on resolution
SSD1963_WrCMD(SSD1963_set_lshift_freq,(uint8_t*)&Parameter, 3);
Parameter=0x0020;   //LCD SPECIFICATION
SSD1963_WrCMD(SSD1963_set_lcd_mode,(uint8_t*)&Parameter, 2);
Parameter=SSD1963_HDP;  //Set HDP
SSD1963_WrPAR((uint8_t*)&Parameter, 2);
Parameter=SSD1963_VDP;  //Set VDP
SSD1963_WrPAR((uint8_t*)&Parameter, 3);
Parameter=SSD1963_HT;  //Set HT HSYNC
SSD1963_WrCMD(SSD1963_set_hori_period,(uint8_t*)&Parameter, 2);
Parameter=SSD1963_HPS;  //Set HPS
SSD1963_WrPAR((uint8_t*)&Parameter, 2);
Parameter=SSD1963_HPW;  //Set HPW
SSD1963_WrPAR((uint8_t*)&Parameter, 1);
Parameter=SSD1963_LPS;  //Set LPS
SSD1963_WrPAR((uint8_t*)&Parameter, 3);
Parameter=SSD1963_VT;  //Set VT VSYNC
SSD1963_WrCMD(SSD1963_set_vert_period,(uint8_t*)&Parameter, 2);
Parameter=SSD1963_VPS;  //Set VPS
SSD1963_WrPAR((uint8_t*)&Parameter, 2);
Parameter=SSD1963_VPW;  //Set VPW
SSD1963_WrPAR((uint8_t*)&Parameter, 1);
Parameter=SSD1963_FPS;  //Set FPS
SSD1963_WrPAR((uint8_t*)&Parameter, 2);
Parameter=0x05;   //0x000F;    //GPIO[3:0] out 1
SSD1963_WrCMD(SSD1963_set_gpio_value,(uint8_t*)&Parameter, 1);
Parameter=0x0107;   //GPIO0 normal GPIO3=input, GPIO[2:0]=output
SSD1963_WrCMD(SSD1963_set_gpio_conf,(uint8_t*)&Parameter, 2);
Parameter=0x00;   //rotation
SSD1963_WrCMD(SSD1963_set_address_mode,(uint8_t*)&Parameter, 1);
Delay_ms(50);
Parameter=0x8006;  //set PWM for B/L
SSD1963_WrCMD(SSD1963_set_pwm_conf,(uint8_t*)&Parameter, 2);
Parameter=0x0000f001;
SSD1963_WrPAR((uint8_t*)&Parameter, 4);
Parameter=0x0d;   //设置动态背光控制配置
SSD1963_WrCMD(SSD1963_set_dbc_conf,(uint8_t*)&Parameter, 1);
   
Parameter=0x03;   //03:16-bit (565 format)
SSD1963_WrCMD(SSD1963_set_pixel_data_interface,(uint8_t*)&Parameter, 1);
// SSD1963_WrCMD(SSD1963_enter_invert_mode,(uint8_t*)&Parameter, 0); //进入图形颜色翻转模式
// Parameter=0x01808080; //处理机允许  饱和度值  亮度 对比度
// SSD1963_WrCMD(SSD1963_set_post_proc,(uint8_t*)&Parameter, 4);
SSD1963_Fill(BLACK);
SSD1963_WrCMD(SSD1963_set_display_on,(uint8_t*)&Parameter, 0); //display on
Delay_ms(5);
}
void SSD1963_Fill(uint16_t color)
{
uint32_t Parameter;
Parameter=0;
SSD1963_WrCMD(SSD1963_set_column_address,(uint8_t*)&Parameter, 2);
Parameter=SSD1963_HDP;
SSD1963_WrPAR((uint8_t*)&Parameter, 2);
Parameter=0;
SSD1963_WrCMD(SSD1963_set_page_address,(uint8_t*)&Parameter, 2);
Parameter=SSD1963_VDP;
SSD1963_WrPAR((uint8_t*)&Parameter, 2);
SSD1963_WrCMD(SSD1963_write_memory_start,(uint8_t*)&Parameter, 0);
for(uint32_t i=0;i<130560;i++){SSD1963_WrRAM(&color, 1);}
}
void LCD_test(void)
{
uint16_t i=0,color[]={BLACK, NAVY, DGREEN, DCYAN, MAROON, PURPLE, OLIVE, LGRAY, DGRAY, BLUE, GREEN, CYAN, RED, MAGENTA, YELLOW, WHITE};
while(1)
{
  if(i++>(sizeof(color)/sizeof(color[0])))i=0;
  SSD1963_Fill(color);Delay_ms(5000);
}
}
void LCD_Configuration(void)
{
NANOEBI_Init();
SSD1963_Init();
printf("REVSH(0x1234)=0x%04x\n\r",__REVSH(0x1234));
LCD_test();
EBI_test();
}

//代码完毕
--缥缈九哥测试

#70 Cortex M0/M3/M4/M7 » 基于M0516的SPI驱动的10X7段共阳数码管的TM1668驱动程序--缥缈九哥 » 2020-05-09 18:34:07

缥缈九哥
回复: 0

测试了一个用M0516的SPI驱动TM1668驱动的10个7段数码管驱动,需要做行列段的转换驱动表,请同行们指正。
源码:

/******************************************************************************
* @file     tM1668.c
* @brief    The Driver code for 10 7-Segment-Digital LED
* @version  1.0.0
* @date     06, december 2013
*
* @note
* Copyright (C) 2000-2013 PM9GZY by yuanxihua@21cn.com. All rights reserved.
******************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include <stdio.h>
#include <string.h>
#include "M051Series.h"
#include "rfid.h"
/*
//make by yuanxihua@21cn.com
____________________________________________
|        M0517LBN                                          TM1668                |
|                                                                                         |
|        P14        SPISS0                ---->                STB                        |
|        P15        MOSI0                 ---->                DIO                        |
|        P16        MISO0                 <----                DIO                        |
|        P17        SCLK0                ---->                CLK                        |
|___________________________________________|
*/
//const unsigned char  TM1668_7X8_CODE[]={0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x77, 0X7F, 0x39, 0x3F, 0x79, 0x71};/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
const unsigned short int TM1668_10X7_CODE[]={0xffed,0x2f9f,0x2ffb,0x7b6d,0xfd45,0xff71,0xcf7c};
void SPI0_Init(void);
void SPI0_Write_Byte(uint8_t data);
void TM1668_Init(void){SPI0_Init();}
void TM1668_Read_Key(uint8_t *key);
void TM1668_Write_ADDR_INC(uint8_t *data);
void TM1668_DISPLAY(uint8_t *led);
void TM1668_Number(uint32_t data1,uint32_t data2);
void SPI0_Init(void)
{
    /* Unlock protected registers */
    SYS_UnlockReg();
        
    /* Set P1.4, P1.5, P1.6, P1.7 for SPI0 */
    SYS->P1_MFP = SYS_MFP_P14_SPISS0 | SYS_MFP_P15_MOSI_0 | SYS_MFP_P16_MISO_0 | SYS_MFP_P17_SPICLK0;
    /* Configure SPI0 as a master, clock idle high, rising clock edge Tx, rising edge Rx and 8-bit LSB transaction */
    SPI0->CNTRL = SPI_CNTRL_MASTER_MODE | SPI_CNTRL_CLK_IDLE_HIGH | SPI_CNTRL_TX_RISING |
                                  SPI_CNTRL_RX_RISING   | SPI_CNTRL_LSB_FIRST     | SPI_CNTRL_TX_BIT_LEN(8);
                                         
        /* SPI_SSR setting to force SPI master SS signal to high by software */
        SPI0->SSR = SPI_SSR_SW_SS_PIN_HIGH;
        
        /* Disable the automatic slave select function of the user-specified SPI port */
        _SPI_DISABLE_HW_AUTO_SLAVE_SELECT(SPI0);
    /* Set IP clock divider. SPI clock rate = HCLK / ((1+1)*2) = 12MHz */
    SPI0->DIVIDER = (SPI0->DIVIDER & (~SPI_DIVIDER_DIVIDER_Msk)) | SPI_DIVIDER_DIV(1);
        
        /* Clear Tx register of SPI1 to avoid send non-zero data to Master. Just for safe. */
    _SPI_WRITE_TX_BUFFER0(SPI1, 0);
        /* Lock protected registers */
    SYS_LockReg();
}
void SPI0_Write_Byte(uint8_t data)
{
        //片选脚设为低电平状态
        SPI0->SSR = SPI_SSR_SW_SS_PIN_LOW;
        //发送数据
        _SPI_WRITE_TX_BUFFER0(SPI0, data);_SPI_SET_GO(SPI0);
        //等待发送数据完毕
        while(_SPI_GET_BUSY_STATUS(SPI0)){;}
        //片选脚设为高电平状态
        SPI0->SSR = SPI_SSR_SW_SS_PIN_HIGH;
}
void TM1668_Read_Key(uint8_t *key)
{
        //片选脚设为低电平状态
        SPI0->SSR = SPI_SSR_SW_SS_PIN_LOW;
        //Command1: 数据读写设置命令
        //发送数据
        _SPI_WRITE_TX_BUFFER0(SPI0, 0x42);_SPI_SET_GO(SPI0); //读键扫数据
        //等待发送数据完毕
        while(_SPI_GET_BUSY_STATUS(SPI0)){;}
        //配置MOSI为高阻输入的AIN口
        SYS->P1_MFP = SYS_MFP_P15_AIN5;
    for(uint8_t i=0;i<5;i++)
    {
                SYS->P1_MFP = SYS_MFP_P15_MOSI_0;
                //发送数据
                _SPI_WRITE_TX_BUFFER0(SPI0, 0xff);_SPI_SET_GO(SPI0);
                //等待发送数据完毕
                while(_SPI_GET_BUSY_STATUS(SPI0)){;}
                //读取数据
                 key=_SPI_GET_RX0_DATA(SPI0);
    }
        //配置P15为MOSI口
        SYS->P1_MFP = SYS_MFP_P15_MOSI_0;
        //片选脚设为高电平状态
        SPI0->SSR = SPI_SSR_SW_SS_PIN_HIGH;
}
void TM1668_Write_ADDR_INC(uint8_t *data)
{
        //Command1: 显示模式设置命令
        SPI0_Write_Byte(0x03);//显示模式:7位10段
        //Command2: 数据读写设置命令
        SPI0_Write_Byte(0x40);//写数据到显示寄存器
    //片选脚设为低电平状态
        SPI0->SSR = SPI_SSR_SW_SS_PIN_LOW;
        //Command3: 显示地址设置命令
        _SPI_WRITE_TX_BUFFER0(SPI0, 0xC0);_SPI_SET_GO(SPI0);//显示地址=0X00
    //等待传送退出
    while(_SPI_GET_BUSY_STATUS(SPI0)){;}
        for(uint32_t i=0;i<14;i++)//Data1~n: 显示数据,以Command3指定的地址为起始地址(最多14 bytes)
        {
                //发送数据
                _SPI_WRITE_TX_BUFFER0(SPI0, data);_SPI_SET_GO(SPI0);
                //等待发送数据完毕
                while(_SPI_GET_BUSY_STATUS(SPI0)){;}
        }
        //片选脚设为高电平状态
        SPI0->SSR = SPI_SSR_SW_SS_PIN_HIGH;
        //Command4: 显示控制命令
        SPI0_Write_Byte(0x88);//显示开,亮度脉冲宽度为1/16:0x88,设置脉冲宽度为14/16:0x8F
}
void TM1668_DISPLAY(uint8_t *led)
{
        uint16_t TM1668[7],*code=(uint16_t*)TM1668_10X7_CODE;
        memset(TM1668,0,sizeof(TM1668));
//        for(uint8_t i=0;i<10;i++){DBG_PRINTF("led[%d]=%d\n\r",i,led);}
        for(uint8_t i=0;i<10;i++){for(uint8_t j=0;j<7;j++){TM1668[j]|=((led>0xf)?0:(code[j]>>led)&1)<<i;}}
        TM1668_Write_ADDR_INC((uint8_t *)(&TM1668[0]));
}
void TM1668_Number(uint32_t data1,uint32_t data2)
{
        uint8_t led[10],*p=&led[3],*q=&led[9];
        if((data1>9999)||(data2>999999)) return;
        memset(led,' ',sizeof(led));led[3]=led[9]=0;
        for(uint32_t i=data1;i!=0;i/=10){*p--=i%10;}
        for(uint32_t i=data2;i!=0;i/=10){*q--=i%10;}
//        for(uint8_t i=0;i<10;i++){DBG_PRINTF("led[%d]=%d\n\r",i,led);}
        TM1668_DISPLAY(led);
}
void TM1668_Test(void)
{
        uint8_t i=0;
        TM1668_Init();
/*    while(1)
    {
                //SPI0_Write_Byte(0x55);
                if(++i>9)i=0;
                uint32_t data0=i*10+i,data1=data0*100+data0,data2=data1*100+data0;
                DBG_PRINTF("*** 9G-M0517LBN V1.00 %04d %06d...\n\r",data1,data2);
                TM1668_Number(data1,data2);
                for(uint16_t i=0;i<500;i++){SYS_SysTickDelay(1000);}
    }
*/
        i=i;
        uint32_t j=0,k=0;
    while(1)
    {
                //SPI0_Write_Byte(0x55);
                if(j++>9999){j=0;} if(k++>999999)k=0;
                DBG_PRINTF("*** 9G-M0517LBN V1.00 %04d %06d...\n\r",j,k);
                TM1668_Number(j,k);
//                for(uint16_t i=0;i<100;i++){SYS_SysTickDelay(1000);}
    }
}

//缥缈九哥测试通过

#71 Cortex M0/M3/M4/M7 » 基于新唐NUC123的3.0的BSP包的PCF8563驱动程序--缥缈九哥 » 2020-05-09 18:32:40

缥缈九哥
回复: 0

基于新唐NUC123的3.0的BSP包的PCF8563驱动程序

源码如下:

/******************************************************************************
 * @file     pcf8563.c
 * @brief    The Driver code for PCF8563 with NUC123ZD4AN0
 * @version  1.0.0
 * @date     22, June, 2018
 *
 * @note
 * Copyright (C) 2000-2016 PM9GZY by yuanxihua@21cn.com. All rights reserved.
 ******************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/*
_________________________________________________
| NUC123ZD4AN0     PCF8563  |
|            |
| SDA1 - PA10  <--->  SDA   |
| SCL1 - PA11   --->  SCL   |
| INT0 -  PB14  <---  INT   |
|_______________________________________________|
*/
/* Private typedef -----------------------------------------------------------*/
typedef enum {START=0,STOP,ACK,NAK}i2c_status_t;
typedef struct
{
 uint8_t CTL_status[2];
 uint8_t VL_second;
 uint8_t TM_minute;
 uint8_t TM_hour;
 uint8_t TM_day;
 uint8_t TM_weekday;
 uint8_t CTY_month;
 uint8_t TM_year;
 uint8_t AL_minute;
 uint8_t AL_hour;
 uint8_t AL_day;
 uint8_t AL_weekday;
 uint8_t CTL_clkout;
 uint8_t CTL_timer;
 uint8_t TM_timer;
}pcf8563_t;

//#define pbcd_to_byte(x)  (((((x)>>4)&0x0f)*10)+((x)&0x0f))
//#define byte_to_pbcd(x)  (((((x)/10)&0x0f)<<4)+(((x)%10)&0x0f))
/* Private define ------------------------------------------------------------*/
#define PCF8563_SLAVEADDR          0xA2    /* Clock i2c slave address */
#define PCF8563_CLK_HZ           100000    /* Clock i2c speed */
#define PCF8563_I2C_WAIT_US      100000    /* Clock wait time */
/* Private macro -------------------------------------------------------------*/
void PCF8563_Get_Time(struct tm *Time);
void PCF8563_Set_Time(struct tm Time);
/* Private variables ---------------------------------------------------------*/
uint8_t pbcd_to_byte(uint8_t pbcd)
{
 uint8_t msb,lsb;
 msb = (pbcd >> 4);
 lsb = pbcd & 0xf;
 if((msb>9)||(lsb>9)){return(99);}
 else{return((10*msb)+lsb);}
}  
uint8_t byte_to_pbcd(uint8_t bin)
{
 if(bin>=99){return(0x99);}/* overflow? */
 else{return(((bin/10)<<4)|(bin%10));}
}
 
static void CLK_SysTickDelayMs(uint32_t ms)
{
 for(uint32_t i=0;i<ms;i++){CLK_SysTickDelay(1000);}
}
void I2C1_Configuration(void)
{
 /* Unlock protected registers */
    SYS_UnlockReg();
 
    /* Set GPA multi-function pins for I2C1 SDA and SCL */
 SYS->GPA_MFP &= ~(SYS_GPA_MFP_PA10_Msk | SYS_GPA_MFP_PA11_Msk);
    SYS->GPA_MFP |= (SYS_GPA_MFP_PA10_I2C1_SDA | SYS_GPA_MFP_PA11_I2C1_SCL);
    SYS->ALT_MFP &= ~(SYS_ALT_MFP_PA10_Msk | SYS_ALT_MFP_PA11_Msk);
    SYS->ALT_MFP |= (SYS_ALT_MFP_PA10_I2C1_SDA | SYS_ALT_MFP_PA11_I2C1_SCL);
 
 /* Enable I2C1 module clock */
    CLK_EnableModuleClock(I2C1_MODULE);

 /* reset I2C1 modules */
 SYS_ResetModule(I2C1_RST);
  
 /* Get I2C1 clock */
// DBG_PRINTF("I2C1 clock %d Hz\n", I2C_GetClockFreq(I2C1));
 /* Lock protected registers */
    SYS_LockReg();
}

static void I2C_SEND_STATUS(I2C_T *i2c,i2c_status_t status)  
{
 uint32_t i=PCF8563_I2C_WAIT_US;
 if(status==START){I2C_SET_CONTROL_REG(i2c, I2C_I2CON_STA_SI); }else   //set start
 if(status==STOP ){I2C_SET_CONTROL_REG(i2c, I2C_I2CON_STO_SI); }else  //set stop
 if(status==ACK  ){I2C_SET_CONTROL_REG(i2c, I2C_I2CON_SI_AA); }else  //set ack
 if(status==NAK  ){I2C_SET_CONTROL_REG(i2c, I2C_I2CON_SI);  }else{;} //set nack
 while((I2C_GetIntFlag(i2c)==0)&&(i--)){CLK_SysTickDelay(1);};
// DBG_PRINTF("I2C_SS STATUS=0x%02x\n\r",I2C_GET_STATUS(i2c));
}

static void I2C_SEND_DATA(I2C_T *i2c,uint8_t data,i2c_status_t ack)  
{
 uint32_t i=PCF8563_I2C_WAIT_US;
 I2C_SET_DATA(i2c, data);
 if(ack==ACK){I2C_SET_CONTROL_REG(i2c, I2C_I2CON_SI_AA);  }else  //ACK
 if(ack==NAK){I2C_SET_CONTROL_REG(i2c, I2C_I2CON_SI);  }else{;} //NACK
 while((I2C_GetIntFlag(i2c)==0)&&(i--)){CLK_SysTickDelay(1);};
// DBG_PRINTF("I2C_SD=0x%02x STATUS=0x%02x\n\r",data,I2C_GET_STATUS(i2c));
}

static uint8_t I2C_READ_DATA(I2C_T *i2c,i2c_status_t ack)  
{
 uint32_t i=PCF8563_I2C_WAIT_US;
 while((I2C_GetIntFlag(i2c)==0)&&(i--)){CLK_SysTickDelay(1);};
 uint8_t data=I2C_GET_DATA(i2c);
 if(ack==ACK){I2C_SET_CONTROL_REG(i2c, I2C_I2CON_SI_AA);  }else  //ACK
 if(ack==NAK){I2C_SET_CONTROL_REG(i2c, I2C_I2CON_SI);  }else{;} //NACK
// DBG_PRINTF("I2C_RD STATUS=0x%02x\n\r",I2C_GET_STATUS(i2c));
 return data;
}

void PCF8563_Get_Time(struct tm *Time)
{
 uint8_t buf[16],i;
 
 I2C1_Configuration();
 //i2c bus open 
 I2C_Open(I2C1, PCF8563_CLK_HZ);
 
 //send i2c start
 I2C_SEND_STATUS(I2C1,START);
    //send slave address & writer command
 I2C_SEND_DATA(I2C1,0xa2,ACK);
 //send register address
 I2C_SEND_DATA(I2C1,0x00,ACK);
   
 //send i2c start
 I2C_SEND_STATUS(I2C1,START);
 //send slave address & read command
 I2C_SEND_DATA(I2C1,0xa3,ACK);

 uint8_t tmp=I2C_READ_DATA(I2C1,ACK);
 for(i=0;i<15;i++)
 {
  //receive data with ack
  buf[i]= I2C_READ_DATA(I2C1,ACK);
  CLK_SysTickDelay(100);
 }
 //receive data with nak
 buf[i]= I2C_READ_DATA(I2C1,NAK);

 //send i2c stop
 I2C_SEND_STATUS(I2C1,STOP);
 
 CLK_SysTickDelay(100);    
 I2C_Close(I2C1);
// DBG_PRINTF("\n\rGETBUF:");for(i=0;i<16;i++){printf("%02x ",buf[i]);}

// memset(Time,0,sizeof(struct tm));
 Time->tm_sec  = pbcd_to_byte(buf[2]&0x7f);
 Time->tm_min  = pbcd_to_byte(buf[3]&0x7f);
 Time->tm_hour  = pbcd_to_byte(buf[4]&0x3f);
 Time->tm_mday  = pbcd_to_byte(buf[5]&0x3f);
 Time->tm_mon  = pbcd_to_byte(buf[7]&0x1f)-1; 
 Time->tm_year  = pbcd_to_byte(buf[8])+100;
}
void PCF8563_Set_Time(struct tm Time)
{
 uint8_t buf[16],i;
 
 buf[0]=0;
 buf[1]=0;
 buf[2]=byte_to_pbcd(Time.tm_sec);
 buf[3]=byte_to_pbcd(Time.tm_min);
 buf[4]=byte_to_pbcd(Time.tm_hour);
 buf[5]=byte_to_pbcd(Time.tm_mday);
 buf[7]=byte_to_pbcd(Time.tm_mon)+1;
 buf[8]=byte_to_pbcd(Time.tm_year%100);
 
// DBG_PRINTF("\n\rSETBUF:");for(i=0;i<16;i++){printf("%02x ",buf[i]);}
 I2C1_Configuration(); 
 //i2c bus open 
 I2C_Open(I2C1, PCF8563_CLK_HZ);
 
 //send i2c start
 I2C_SEND_STATUS(I2C1,START);
    //send slave address & writer command
 I2C_SEND_DATA(I2C1,0xa2,ACK);
 //send register address
 I2C_SEND_DATA(I2C1,0x00,ACK);
 
 for(i=0;i<15;i++)
 {
  //send data with ack
  I2C_SEND_DATA(I2C1,buf[i],ACK);
  CLK_SysTickDelay(100);
 }
 //send data with nak
 I2C_SEND_DATA(I2C1,buf[i],NAK);
    
    //send i2c stop
 I2C_SEND_STATUS(I2C1,STOP);
  
 CLK_SysTickDelay(100);
 I2C_Close(I2C1);
}
uint8_t PCF8563_Chk_Time(struct tm *t)
{
 uint32_t year=t->tm_year, month=t->tm_mon, day=t->tm_mday;   //防止修改指针
 uint32_t hour=t->tm_hour, minute=t->tm_min, second=t->tm_sec;  //防止修改指针
 if((year<2010)||(year>2030)){return 0;}
 if((month<1)||(month>12)){return 0;}
 if((day<1)||(day>31)){return 0;}
 if((month==4||month==6||month==9||month==11)&&(day>30)){return 0;}
 if(month==2){if(year%4){if(day>28){return 0;}}else{if(day>29){return 0;}}}
 if((hour>23)||(minute>59)||(second>60)){return 0;}
 return 1;
}

void PCF8563_test(void)
{
 __align(4) struct tm Time;
  
#if 0
 const char Month[12][4]= {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};char sMonth[4]= {0};
 const char *DataStr = __DATE__; //Aug 20 2016
 const char *TimeStr = __TIME__; //20:12:38
    sscanf(DataStr, "%s %d %d", sMonth, &Time.tm_mday, &Time.tm_year);
    sscanf(TimeStr, "%d:%d:%d", &Time.tm_hour, &Time.tm_min, &Time.tm_sec);
 for(int i=0;i<12;i++){if(strncmp(sMonth, Month[i],3)==0){Time.tm_mon=i;break;}}

 Time.tm_year  -= 1900;  /* years since 1900 */
// Time.tm_mon  = 8-1;   /* months since January, 0 to 11 */
// Time.tm_mday  = 20;   /* day of the month, 1 to 31 */
// Time.tm_hour  = 18;   /* hours since midnight, 0 to 23 */
// Time.tm_min  = 43;   /* minutes after the hour, 0 to 59 */
 Time.tm_sec  +=10;   /* seconds after the minute, 0 to 60
         (0 - 60 allows for the occasional leap second) */
 PCF8563_Set_Time(Time);

 while(1)
#endif
 {
  PCF8563_Get_Time(&Time);
  time_t t=mktime(&Time); // printf("t=%d %s",t, ctime(&t));
  printf("%s", asctime(&Time));

  char str[80]; strftime(str,100,"GET Time:%F %H:%M:%S\n\r",&Time); printf("%s", str);     
  CLK_SysTickDelayMs(1000);
  
  struct tm a;
  a.tm_year  = 100;  /* years since 1900 */
  a.tm_mon  = 0;  /* months since January, 0 to 11 */
  a.tm_mday  = 1;  /* day of the month, 1 to 31 */
  a.tm_hour  = 0;  /* hours since midnight, 0 to 23 */
  a.tm_min  = 0;  /* minutes after the hour, 0 to 59 */
  a.tm_sec  = 0;  /* seconds after the minute, 0 to 60 */
  
  time_t p=mktime(&a);
  printf("p=0x%08x = %d , %s",p,p,ctime(&p));
  //p=0x386d4380 = 946684800 , Sat Jan  1 00:00:00 2000
  t=0x1F4DC49F+p;//1986-08-23 14:11:43
  printf("t=0x%08x = %d , %s",t,t,ctime(&t));
  //t=1471875103 Mon Aug 22 14:11:43 2016
 }
 
}

//代码完毕。

#72 Cortex M0/M3/M4/M7 » 基于新唐NUC123的3.0的BSP包的FM25CL64BG驱动开发--缥缈九哥 » 2020-05-09 18:31:06

缥缈九哥
回复: 0

基于新唐NUC123的3.0的BSP包的FM25CL64BG驱动开发

源码如下:

/**************************************************************************//**
 * @file     fm25640c.c
 * @version  V3.00
 * $Revision: 5 $
 * $Date: 16/08/04 11:18a $
 * @brief    Demonstrate how to perform timer counting in periodic mode.
 * @note
 * Copyright (C) 2014~2016 PM9GZY Technology Corp. yuanxihua@21cn.com All rights reserved.
 ******************************************************************************/
 
/* Includes ------------------------------------------------------------------*/
#include <stdio.h>
#include "NUC123.h"
/*
_________________________________________________
| NUC123ZD4AN0     FM25CL64BG |
|            |
| PC8  SS10  ---->  CS   |
| PC9  SPICLK1  ---->  SCK   |
| PC10 MISO10  <----  SO   |
| PC11 MOSI10  ---->  SI   |
|_______________________________________________|
*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
//#define  FM25CL64BG_CS   PC8
#define  FM25CL64BG_SIZE  8*1024
//FM25CL64BG命令
#define   FM25CL64BG_WREN  0x06
#define   FM25CL64BG_WRDI  0x04
#define   FM25CL64BG_RDSR  0x05ff
#define   FM25CL64BG_WRSR  0x0100
#define   FM25CL64BG_READ  0x030000FF
#define   FM25CL64BG_WRITE 0x02000000
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
void FM25CL64BG_Init(void);
void FM25CL64BG_Read (uint32_t addr, uint8_t *buf, uint32_t len);
void FM25CL64BG_Write(uint32_t addr, uint8_t *buf, uint32_t len);
void FM25CL64BG_Write_Byte(uint32_t addr,uint8_t wrdata);
void FM25CL64BG_Write_Status_Register(uint8_t wrdata);
uint8_t FM25CL64BG_Read_Byte(uint32_t addr);
uint8_t FM25CL64BG_Read_Status_Register(void);
void SPI1_Send_Data(uint32_t wrdata,uint8_t bits);

/* Private functions ---------------------------------------------------------*/

/**
  * @brief  Main program.
  * @param  None
  * @retval None
  */
void FM25CL64BG_Test(void)
{
 uint32_t i;
 
 /* Configure the FM25CL64BG */
 FM25CL64BG_Init();

 while(0)
 { 
//  SPI1_Send_Data(0x55, 8);
//  SPI_SET_SS0(SPI1); SPI1_Send_Data(0x55, 8);SPI_CLR_SS0(SPI1); //写0x55测试SPI接口
//  FM25CL64BG_Write_Byte(0xCC, 0x55);
//  FM25CL64BG_Read_Byte (0xCC); 
//  FM25CL64BG_Read_Status_Register();
 }
 
 FM25CL64BG_Write_Status_Register(0x00);
 printf("FM25CL64BG_Read_Status_Register() = 0x%02x \n\r",FM25CL64BG_Read_Status_Register());
 FM25CL64BG_Write_Byte(0xAA, 0x55);
 FM25CL64BG_Write_Byte(0x55, 0xAA);
 printf("FM25CL64BG_Read_Byte(0xAA) = 0x%02x \n\r",FM25CL64BG_Read_Byte(0xAA));
 printf("FM25CL64BG_Read_Byte(0x55) = 0x%02x \n\r",FM25CL64BG_Read_Byte(0x55));

 while(1)
 {
  for(i=0;i<FM25CL64BG_SIZE;i++)
  {FM25CL64BG_Write_Byte(i, i&0xff);}
  CLK_SysTickDelay(300000);
  for(i=0;i<FM25CL64BG_SIZE;i++)
  {
   //for display
   if((i%16)== 0){printf("\n\r%08xh:",i);}
   printf(" %02x",FM25CL64BG_Read_Byte(i));
   if((i%16)==15){printf(" ;");}
   //display  end
  }
  CLK_SysTickDelay(300000); 
 }
}
// SPI1_Send_Data(FM25640C_WREN,8);
// SPI1_Send_Data(FM25640C_WRDI,8);

void FM25CL64BG_Read(uint32_t addr, uint8_t *buf, uint32_t len)
{
 uint32_t i;
 for(i=0;i<len;i++)
 {buf[i] = FM25CL64BG_Read_Byte(addr+i);}
}
void FM25CL64BG_Write(uint32_t addr, uint8_t *buf, uint32_t len)
{
 uint32_t i;
 for(i=0;i<len;i++)
 {FM25CL64BG_Write_Byte(addr+i,buf[i]);}
}
uint8_t FM25CL64BG_Read_Byte(uint32_t addr)
{
 uint32_t rddata,tmpdata=FM25CL64BG_READ;

 tmpdata |= (addr << 8); 
 SPI1_Send_Data(tmpdata,32);
 rddata = SPI_READ_RX0(SPI1);
 return (uint8_t)rddata;
}
void FM25CL64BG_Write_Byte(uint32_t addr, uint8_t wrdata)
{
 uint32_t tmpdata=FM25CL64BG_WRITE;
 
 SPI1_Send_Data(FM25CL64BG_WREN,8);    //中:使能写操作//Write Enable
 tmpdata |= (addr << 8) + wrdata;
 SPI1_Send_Data(tmpdata,32);
}
uint8_t FM25CL64BG_Read_Status_Register(void)
{
 uint32_t rddata;
 
 SPI1_Send_Data(FM25CL64BG_RDSR,16);
 rddata = SPI_READ_RX0(SPI1);
 return (uint8_t)rddata;
}
void FM25CL64BG_Write_Status_Register(uint8_t wrdata)
{
 uint16_t dat=FM25CL64BG_WRSR | wrdata;
 
 SPI1_Send_Data(FM25CL64BG_WREN,8);    //中:使能写操作//Write Enable
 SPI1_Send_Data(dat,16);
}
void SPI1_Send_Data(uint32_t wrdata, uint8_t bits)
{
 SPI1->CNTRL = (SPI1->CNTRL&0xFFFFFF07) | ((bits&0x1f) << SPI_CNTRL_TX_BIT_LEN_Pos);
 
 /* Write to TX register */
 SPI_WRITE_TX0(SPI1, wrdata);
 /* Trigger SPI1 data transfer */
 SPI_TRIGGER(SPI1);
 /* Check SPI1 busy status */
 while(SPI_IS_BUSY(SPI1));
}
void SPI1_Init(void)
{
 /* Select HCLK as the clock source of SPI1 */
    CLK_SetModuleClock(SPI1_MODULE, CLK_CLKSEL1_SPI1_S_HCLK, MODULE_NoMsk);

    /* Enable SPI1 peripheral clock */
    CLK_EnableModuleClock(SPI1_MODULE);

    /* Setup SPI1 multi-function pins */
 SYS->GPC_MFP &= ~(SYS_GPC_MFP_PC8_Msk | SYS_GPC_MFP_PC9_Msk | SYS_GPC_MFP_PC10_Msk | SYS_GPC_MFP_PC11_Msk);
 SYS->GPC_MFP |= SYS_GPC_MFP_PC8_SPI1_SS0 | SYS_GPC_MFP_PC9_SPI1_CLK | SYS_GPC_MFP_PC10_SPI1_MISO0 | SYS_GPC_MFP_PC11_SPI1_MOSI0;
 
 SYS->ALT_MFP1 &= ~(SYS_ALT_MFP1_PC8_Msk | SYS_ALT_MFP1_PC9_Msk | SYS_ALT_MFP1_PC10_Msk | SYS_ALT_MFP1_PC11_Msk);
 SYS->ALT_MFP1 |= SYS_ALT_MFP1_PC8_SPI1_SS0 | SYS_ALT_MFP1_PC9_SPI1_CLK | SYS_ALT_MFP1_PC10_SPI1_MISO0 | SYS_ALT_MFP1_PC11_SPI1_MOSI0;

    /*---------------------------------------------------------------------------------------------------------*/
    /* Init SPI                                                                                                */
    /*---------------------------------------------------------------------------------------------------------*/
    /* Configure as a master, clock idle low, 32-bit transaction, drive output on falling clock edge and latch input on rising edge. */
    /* Set IP clock divider. SPI clock rate = 36MHz */
    SPI_Open(SPI1, SPI_MASTER, SPI_MODE_0, 32, 36000000);

    /* Enable the automatic hardware slave select function. Select the SS pin and configure as low-active. */
    SPI_EnableAutoSS(SPI1, SPI_SS0, SPI_SS_ACTIVE_LOW);
}

void FM25CL64BG_Init(void)
{
 SPI1_Init();
}

//源码完毕

#73 Cortex M0/M3/M4/M7 » 基于STM32的TM1629的驱动代码--缥缈九哥 » 2020-05-09 18:29:42

缥缈九哥
回复: 0

某年写个番禺龙美游戏机IO板用到了STM32F103VBT6及TM1629.写下了一个驱动程序。希望能帮助到有需要的朋友。不多说了,代码如下:

/* Includes ------------------------------------------------------------------*/
#ifdef GAME
#include "stm32f10x.h"
#include "stdio.h"
/** @addtogroup STM32F10x_StdPeriph_Examples
  * @{
  */

/** @addtogroup GPIO_JTAG_Remap
  * @{
  */
/*
_________________________________________________
|	STM32F103						TM1629		|
|												|
|	PC0-3	CSA-CSD		---->		STB 		|
|	PE14	MISO		<----		MISO		|
|	PC6		SCLK		---->		SCLK		|
|	PC7		MOSI		---->		MOSI		|
|	PC4		KEYLED		---->		KEYLED		|
|	PC5		CPULED		---->		CPULED		|
|_______________________________________________|
*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
//TM1629片选 			//STB
#define	TM1629_STB		GPIOC 					/* PC0-PC3			*/
#define	TM1629_CSA		GPIOC, GPIO_Pin_0
#define	TM1629_CSB		GPIOC, GPIO_Pin_1
#define	TM1629_CSC		GPIOC, GPIO_Pin_2
#define	TM1629_CSD		GPIOC, GPIO_Pin_3
//TM1629信号脚
#define	TM1629_SCLK		GPIOC, GPIO_Pin_6		/*PC6	SCLK*/
#define	TM1629_MOSI		GPIOC, GPIO_Pin_7		/*PC7	DIN*/
#define	TM1629_MISO		GPIOE, GPIO_Pin_14		/*PE14	DOUT*/
//键盘指示灯使能
#define	KEY_LAMP_EN		GPIOC, GPIO_Pin_4		/*PC4	RESVIN*/
#define	CPU_LAMP_EN		GPIOC, GPIO_Pin_5		/*PC5	LAMP*/
//TM1629命令
#define	TM1629_ADDR_INC			0x40
#define	TM1629_ADDR_FIXED		0x44
#define	TM1629_ADDR_BASE		0xc0
#define	TM1629_DISP_OFF			0x80
#define	TM1629_DISP_MINON		0x88
#define	TM1629_DISP_MAXON		0x8f
#define	TM1629_DISP_ONX			7
#define	TM1629_DISP_ON			(0x88+TM1629_DISP_ONX)
#define	TM1629_KEY_READ			0x42
//TM1629延时
#define	TM1629_DELAY			2				/* 640ns	*/
//TM1629应用
#define	TM1629_LED_DARK			0x00
#define	TM1629_LED_BRIGHT		0x7F
#define	TM1629_LED_BRIGHT_DOT	0xFF
#define	TM1629_CS_MASK			0xFFF0

#ifdef PART5
#define	TM1629_CS_NONE			7
#else
#define	TM1629_CS_NONE			0
#endif
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
const unsigned char TM1629_CODE[16]=
/*0x0	0x1   0x2   0x3   0x4   0x5   0x6   0x7   0x8   0x9   0xA   0xb   0xC   0xd   0xE   0xF*/
{0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x77, 0X7C, 0x39, 0x5E, 0x79, 0x71};
const unsigned char TM1629_CODE_LED[16]=
/*0x0	0x1   0x2   0x3   0x4   0x5   0x6   0x7   0x8   0x9   0xA   0xB   0xC   0xD   0xE   0xF*/
{0xBF, 0x86, 0xDB, 0xCF, 0xE6, 0xED, 0xFD, 0x87, 0xFF, 0xEF, 0xF7, 0XFF, 0xB9, 0xBF, 0xF9, 0xF1};
const unsigned char TM1629_SEGMENT[8]=
/*  a     b     c     d     e     f     g     h*/
{0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
/* Private function prototypes -----------------------------------------------*/
void TM1629_Test(void);
void TM1629_Configuration(void);
void TM1629_Write_Byte(uint8_t wrdata);
void TM1629_Write_CMD(uint8_t chip,uint8_t wrdata);
void TM1629_Write_CMD2(uint8_t chip,uint8_t wrdata);
uint8_t TM1629_Read_Byte(void);
uint32_t TM1629_Read_Keys(unsigned char chip);
void TM1629_Activation(uint8_t chip); 
void TM1629_Write_Chip(uint8_t chip,uint8_t *led_data);
void TM1629_Write_Led(uint8_t chip,uint8_t led_index,uint8_t led_data);
void TM1629_Write_Leds(uint8_t chip,uint8_t index,uint32_t *data,uint8_t length);
void TM1629_Write_Digital(uint8_t chip,uint8_t led_index,uint8_t led_data);
void TM1629_Write_3Digital(uint8_t chip,uint8_t led_index,uint32_t led_data);
void TM1629_Write_Digitals(uint8_t chip,uint8_t led_index,uint32_t led_data,uint8_t digit_limit);
void TM1629_Write_Segment(uint8_t chip,uint8_t led_index,uint8_t led_data);
extern void SEND_RS485_STRING(char *s);
extern void Delay(__IO uint32_t nTime);
/* Private functions ---------------------------------------------------------*/

/**
  * @brief  Main program.
  * @param  None
  * @retval None
  */
void TM1629_Configuration(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	uint32_t i,j;
	
	/* Enable GPIOC, GPIOE and AFIO clocks */
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOE | RCC_APB2Periph_AFIO, ENABLE);

	/* Enable GPIOC PC0-PC7 output */
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7 ;
	GPIO_Init(GPIOC, &GPIO_InitStructure);	

	GPIO_ResetBits(KEY_LAMP_EN);
	GPIO_ResetBits(CPU_LAMP_EN);
	TM1629_Activation(TM1629_CS_NONE); 
	
	/* Enable GPIOE PE14 input */
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14 ;
	GPIO_Init(GPIOE, &GPIO_InitStructure);
	//全部熄灭
	for(i=1;i<=8;i++)
	{for(j=0;j<16;j++){TM1629_Write_Led(i,j,TM1629_LED_DARK);}}
	GPIO_ResetBits(KEY_LAMP_EN);
}

void TM1629_Write_Byte(uint8_t wrdata)
{
	uint8_t i; uint32_t j;

	for(i=0;i<8;i++)
	{
		GPIO_ResetBits(TM1629_SCLK);		//拉低时钟
		if(wrdata&0x01) 					//最低位判断
		{GPIO_SetBits(TM1629_MOSI);	 }		//最低位为1,则写1到DIN口
  		else
  		{GPIO_ResetBits(TM1629_MOSI);}		//最低位为0,则写0到DIN口
		for(j=0;j<TM1629_DELAY;j++){;}		//delay		
		GPIO_SetBits(TM1629_SCLK);			//拉高时钟		
		for(j=0;j<TM1629_DELAY;j++){;}		//delay
  		wrdata>>=1; 						//数据移到下一位
  	}
}
uint8_t TM1629_Read_Byte(void)
{
	uint8_t i,rddata=0x0; uint32_t j;

	for(i=0;i<8;i++)
	{
		GPIO_ResetBits(TM1629_SCLK);		//拉低时钟
		for(j=0;j<TM1629_DELAY;j++){;}		//delay
		GPIO_SetBits(TM1629_SCLK);			//拉高时钟
		rddata>>=1; 						//数据移到下一位
  		//DOUT为1,最高位付值为1
		if(GPIO_ReadInputDataBit(TM1629_MISO))	//最高位判断	
		{rddata|=0x80;}
		//DOUT为0,最高位付值为0
		for(j=0;j<TM1629_DELAY;j++){;}		//delay
  	}
  	return rddata;
}
void TM1629_Activation(uint8_t chip)
{
	uint16_t temp = (GPIO_ReadOutputData(TM1629_STB)&TM1629_CS_MASK)+chip;
	GPIO_Write(TM1629_STB, temp);
}
void TM1629_Write_CMD(uint8_t chip,uint8_t wrdata)
{	uint32_t j;
	TM1629_Activation(TM1629_CS_NONE); 
	for(j=0;j<TM1629_DELAY;j++){;}//delay
	TM1629_Activation(chip);
	TM1629_Write_Byte(wrdata);
}
void TM1629_Write_CMD2(uint8_t chip,uint8_t wrdata)
{
	TM1629_Write_CMD(chip,wrdata);
	TM1629_Activation(TM1629_CS_NONE); 
}
void TM1629_Write_Led(uint8_t chip,uint8_t led_index,uint8_t led_data)
{
	TM1629_Write_CMD(chip,TM1629_ADDR_FIXED);  
	TM1629_Write_CMD(chip,TM1629_ADDR_BASE+led_index);
	TM1629_Write_Byte(led_data);
	TM1629_Write_CMD2(chip,TM1629_DISP_ON);
}
void TM1629_Write_Digital(uint8_t chip,uint8_t led_index,uint8_t led_data)
{TM1629_Write_Led(chip,led_index,TM1629_CODE[led_data]);}

void TM1629_Write_Segment(uint8_t chip,uint8_t led_index,uint8_t led_data)
{TM1629_Write_Led(chip,led_index,TM1629_SEGMENT[led_data]);}

void TM1629_Write_Leds(uint8_t chip,uint8_t index,uint32_t *data,uint8_t length)
{
	uint8_t i;
	
	TM1629_Write_CMD(chip,TM1629_ADDR_INC);  
	TM1629_Write_CMD(chip,TM1629_ADDR_BASE+index);
	for(i=0;i<length;i++){TM1629_Write_Byte(data[i]);}
	TM1629_Write_CMD2(chip,TM1629_DISP_ON); 
}

void TM1629_Write_3Digital(uint8_t chip,uint8_t led_index,uint32_t led_data)
{
	TM1629_Write_CMD(chip,TM1629_ADDR_INC);  
	TM1629_Write_CMD(chip,TM1629_ADDR_BASE+led_index);
	TM1629_Write_Byte(TM1629_CODE[(led_data%   10)/   1]);
	TM1629_Write_Byte(TM1629_LED_DARK);
	if(led_data>99)TM1629_Write_Byte(TM1629_CODE[(led_data% 1000)/ 100]);
	else TM1629_Write_Byte(TM1629_LED_DARK);
	if(led_data> 9)TM1629_Write_Byte(TM1629_CODE[(led_data%  100)/  10]);
	else TM1629_Write_Byte(TM1629_LED_DARK);
	TM1629_Write_CMD2(chip,TM1629_DISP_ON); 
}
void TM1629_Write_Digitals(uint8_t chip,uint8_t led_index,uint32_t led_data,uint8_t digit_limit)
{
	uint8_t i,data[16];

	data[0]=TM1629_CODE[0];
	for(i=1;i<digit_limit;i++){data[i]=0x0;}
	for(i=0;(led_data>0)&&(i<digit_limit);led_data/=10)
	{data[i++]=TM1629_CODE[led_data%10];}
	
	TM1629_Write_CMD(chip,TM1629_ADDR_INC);  
	TM1629_Write_CMD(chip,TM1629_ADDR_BASE+led_index);
	for(i=0;i<digit_limit;i++)
	{TM1629_Write_Byte(data[i]);}
	TM1629_Write_CMD2(chip,TM1629_DISP_ON); 
}

void TM1629_Write_Chip(uint8_t chip,uint8_t *led_data)
{
	uint8_t i;
	TM1629_Write_CMD(chip,TM1629_ADDR_INC);  
	TM1629_Write_CMD(chip,TM1629_ADDR_BASE);
	for(i=0;i<16;i++){TM1629_Write_Byte(led_data[i]);}
	TM1629_Write_CMD2(chip,TM1629_DISP_ON); 
}

uint32_t TM1629_Read_Keys(uint8_t chip)
{
	uint32_t i,j;
	union {__IO uint32_t u32data;__IO uint8_t u8data[4];} data;

	TM1629_Write_CMD(chip,TM1629_KEY_READ);
	for(j=0;j<TM1629_DELAY;j++){;}//delay
	for(i=0;i<4;i++){data.u8data[i]=TM1629_Read_Byte();	}
	TM1629_Activation(TM1629_CS_NONE); 
	return data.u32data;
}
void TM1629_Clear_All(void)
{
	uint8_t i,data[16];
	for(i=0;i<16;i++){data[i]=0;}
	TM1629_Configuration();
	for(i=1;i<=9;i++)
	{TM1629_Write_Chip(i,data);}
}

#endif
/**
  * @}
  */

/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/

代码完毕。

#74 华芯微特 » 基于MDK-ARM的华芯微特SWM180+RTOS的JLINK开发环境建立--缥缈九哥 » 2020-05-09 18:27:21

缥缈九哥
回复: 8

基于MDK-ARM的华芯微特SWM180+RTOS的JLINK开发环境建立

一,下载软件

1,mdk:MDK-523.EXE
    http://www.keil.com/fid/j34rw9wlgtwj1w3qhmw11ww3fwxbkks16d2wd1/files/eval/mdk523.exe

2,pack:Synwit.SWM32_DFP.1.0.0.pack
    通过代理商或者“yuanxihua@21cn.com”获取此Pack文件。
   
二,安装软件

1,右击 MDK-523.EXE 用管理员权限安装到 C:\Keil ;
2,安装 Synwit.SWM32_DFP.1.0.0.pack 到 C:\Keil\ARM\PACK\Synwit\SWM32_DFP\1.1.0  ;
3,打开MDK-ARM的IDE界面,在菜单的 “project”->“Manage”->“Pack Installer”下刷新在线安装 ARM下的所有PACK包 ;
4,在MDK-ARM的IDE界面,在菜单的 “File”->“License Management”里安装上RL-ARM和 MAK-ARM Plus 的版权。

三,建立工程

1,右击桌面“Keil uVision5” 打开MDK-ARM界面,在菜单的 “project”->“New uVision Project ...”下建立项目“9g-swm180”到:
    “D:\works\9G-CM0\9G-SWM180X”目录下面;

2,在弹出的“Select Device for Target ‘Target1’”选择里选择 “Synwit” 下的“SWM1800 Series”下的“SWM180xB”器件后点击“OK”
    现成项目器件的选择;
   
3,在弹出的“Manage Run-Time Environment”里选择“CMSIS”下的“CORE”和“RTOS(API)”下的“Keil RTX”,以及“Device”下的
    “Startup”及“Driver”下面的所有外设驱动,然后点击“OK”完成项目的建立;

3,在“D:\works\9G-CM0\9G-SWM180X”下建立“source”文件夹,并在MDK-ARM界面左侧“Project”下的“Target 1”下面的“Source Group1”
    修改成“source”文件夹;

4,在MDK-ARM界面“File”->“New...”建立一个空文件后保存到“D:\works\9G-CM0\9G-SWM180X\source”并命名为“main.c”,并且加入到项目的
    左侧的“source”文件夹中;

5,修改“main.c”文件内容如下:
    #include "SWM1800.h"
    int main(void)
    {
        SystemInit();
        GPIO_Init(GPIOA, PIN8 , 1, 0, 0, 0);//GPIOA.8 配置为输出引脚,推挽输出
        while(1){GPIO_InvBit(GPIOA, PIN8);for(int i=0; i<1000000; i++) {;}}
    }

四,配置工程

1,打开MDK-ARM的界面,在菜单的 “Project”->“Options for Target1 ...”下“Target”里选择上“Use MicroLIB”,在“Output”里选择上“Create HEX File”,
    在“Debug”里选择上“J-LINK/J-TRACE Cortex”,并在后面的“Setting”弹出的“Target device settings”里选择上“Cortex-M0”,后点击“OK”,
    退回的“Debug”里面“Port:”下选择端口“SW”,看到能识别IDCODE后点击 “确定”再“OK”完成项目设置;

五,执行工程

1,利用JLINK的SWD口连接目标板到电脑的USB口,在MDK-ARM的界面菜单的 “Debug”->“Start/Stop Session”进行编译下载代码,然后按F5全速
    运行程序。完成实现入门点灯全过程!

六,应用RTX

1,在“main.c”文件前部分加上头文件“#include "cmsis_os.h"”,定义两个进程号 “osThreadId idLED, idCOM;”声明两个进程“void TaskLED(void const *arg);”和“
    void TaskCOM(void const *arg);”定义两个进程“osThreadDef(TaskLED, osPriorityNormal, 1, 0);”和“osThreadDef(TaskCOM, osPriorityNormal, 1, 0);”
2,在“main()”函数中加入RTOS初始化“ osKernelInitialize();”以及创建进程“idLED = osThreadCreate(osThread(TaskLED), NULL);”和“idLED = osThreadCreate(osThread(TaskCOM), NULL);”
    并启动RTOS“osKernelStart();”;

3,添加两个进程实体后“main.c”如下:

    #include "SWM1800.h"
    #include "cmsis_os.h"

    osThreadId idLED, idCOM;
    void TaskLED(void const *arg);
    void TaskCOM(void const *arg);
    osThreadDef(TaskLED, osPriorityNormal, 1, 0);
    osThreadDef(TaskCOM, osPriorityNormal, 1, 0);
    void SerialInit(void);

    int main(void)
    {
        SystemInit();
        osKernelInitialize();
        idLED = osThreadCreate(osThread(TaskLED), NULL);
        idLED = osThreadCreate(osThread(TaskCOM), NULL);
        osKernelStart();
    }

    void TaskLED(void const *arg)
    {
        GPIO_Init(GPIOA, PIN8, 1, 0, 0, 0);    //GPIOA.8配置为输出引脚,推挽输出
        GPIO_Init(GPIOA, PIN9, 1, 0, 0, 0);    //GPIOA.9配置为输出引脚,推挽输出
        GPIO_ClrBit(GPIOA, PIN8);GPIO_SetBit(GPIOA, PIN9);
       
        while(1)
        {
            GPIO_InvBit(GPIOA, PIN8);GPIO_InvBit(GPIOA, PIN9);
            osDelay(500);
        }
    }
    void TaskCOM(void const *arg)
    {
        SerialInit();
        while(1)
        {
            printf("Hi, World!\r\n");
            osDelay(500);
        }
    }
    void SerialInit(void)
    {
        UART_InitStructure UART_initStruct;
       
        PORT_Init(PORTA, PIN0, FUNMUX_UART0_RXD, 1);    //GPIOA.0配置为UART0输入引脚
        PORT_Init(PORTA, PIN1, FUNMUX_UART0_TXD, 0);    //GPIOA.1配置为UART0输出引脚
       
        UART_initStruct.Baudrate = 57600;
        UART_initStruct.RXThresholdIEn = 0;
        UART_initStruct.TXThresholdIEn = 0;
        UART_initStruct.TimeoutIEn = 0;
        UART_Init(UART0, &UART_initStruct);
        UART_Open(UART0);
    }
    int fputc(int ch, FILE *f)
    {
        UART_WriteByte(UART0, ch);   
        while(UART_IsTXBusy(UART0));    
        return ch;
    }

4,在MDK-ARM的界面菜单的 “Debug”->“Start/Stop Session”进行编译下载代码,然后按F5全速
    运行程序。

#75 华芯微特 » 基于华芯微特SWM180CBT6的串口驱动真彩色WS2812灯带的应用实例--缥缈九哥 » 2020-05-09 18:25:24

缥缈九哥
回复: 4

不多说请看注释及源码,有用到或转发的请记住这是缥缈九哥(yuanxihua@21cn.com)原创:

/*******************************************************************************************
WS2812S的标准时序如下:
TH+TL=1.25us±150ns, RES>50us
T0H=0.25us±150ns = 0.10us - 0.40us
T1H=1.00us±150ns = 0.85us - 1.15us
T0L=1.00us±150ns = 0.85us - 1.15us
T1L=0.25us±150ns = 0.10us - 0.40us
占空比取1:3,Bit = 0.290us - 0.350us , T=1.160us - 1.40us 

用UART的TXD驱动WS2812,采用3M即0.333US的波特率。
那么起始位+D0D1D2位组合成0111做为WS2812的0码,D3D4D5D6位0001做为WS2812的1码;
或者起始位+D0D1D2位组合成0001做为WS2812的1码,D3D4D5D6位0111做为WS2812的0码;
而且剩下的D7+结束位+2位字间空隙组合成固定的1111为新的空闲位。
那么只要外置74HC04做反相功能,即可符合标准的WS2812的接收的时序要求。
即是T0H=0.333US,T0L=0.999US,T1H=0.999US,T1L=0.333US;
即是TH+TL=1.332us 小于周期1.4US,而且 IDLE=1.332uS 小于RES的50us时间,以上状态会保持下去。
结论:用连续12个字节的UART信号即可传送一个WS2812显示像素24位数据。
*********************************************************************************************/
#include "SWM1800.h" 
#include "cmsis_os.h"
#include "string.h"
#include <stdlib.h>
typedef __packed struct
{
	uint8_t blue;
	uint8_t green;
	uint8_t red;
	uint8_t white;
}pixel_t; 
void UART1Init(void)
{
	UART_InitStructure UART_initStruct;
	
	PORT_Init(PORTA, PIN0, FUNMUX_UART1_RXD, 1);	//GPIOA.0配置为UART1输入引脚
	PORT_Init(PORTA, PIN1, FUNMUX_UART1_TXD, 0);	//GPIOA.1配置为UART1输出引脚
	
	UART_initStruct.Baudrate 		= 3000000;	//=clk/16/x BIT = 0.333us
	UART_initStruct.TXThreshold 	= 0;		//取值0--7
	UART_initStruct.TXThresholdIEn 	= 0;		//当TX FIFO中数据个数 <= TXThreshold时触发中断
	UART_initStruct.RXThreshold 	= 7;		//取值0--7
	UART_initStruct.RXThresholdIEn 	= 1;		//当RX FIFO中数据个数 >= RXThreshold时触发中断
	UART_initStruct.TimeoutTime 	= 20;		//超时时长 = TimeoutTime/(Baudrate/10) 秒
	UART_initStruct.TimeoutIEn		= 1;		//超时中断,超过 TimeoutTime/(Baudrate/10) 秒没有在RX线上接收到数据时触发中断
	
 	UART_Init(UART1, &UART_initStruct);
	UART_Open(UART1);
}
void Uart1Write(char data)
{
	UART_WriteByte(UART1, data);	
	while(UART_IsTXBusy(UART1)); 	
}
#if 0
void Uart1Test(void)
{	
	UART1Init();
	while(1){Uart1Write(0x55);}
}
void Ws2812Reset(void)
{	
	GPIO_Init(GPIOA, PIN1, 1, 0, 0, 0);				//GPIOA.1配置为输出引脚,推挽输出
	GPIO_SetBit(GPIOA, PIN1);
	osDelay(1);//延时60us以上
	PORT_Init(PORTA, PIN1, FUNMUX_UART1_TXD, 0);	//GPIOA.1配置为UART1输出引脚
}
#endif
void Ws2812WriteByte(uint8_t byte)
{
	for(uint8_t i=0;i<4;i++)
	{
		uint8_t data=((byte&0x80)?0x04:0x07)|((byte&0x40)?0x40:0x70)|0x80; // D0-D2:D3-D6:D7
		Uart1Write(data);
		byte<<=2;
	}
}
void Ws2812Pixel(pixel_t *pixel,uint32_t length)
{
	osDelay(1);//延时1ms以复位
	__disable_irq();
	for(uint32_t i=0;i<length;i++)
	{
		Ws2812WriteByte(pixel[i].green);	//绿色
		Ws2812WriteByte(pixel[i].red);		//红色
		Ws2812WriteByte(pixel[i].blue);		//蓝色
	}
	__enable_irq();
}
void Ws2812Test(void)
{
	uint32_t i=0,j,color[8],len=8,dly=4;
	UART1Init();
	while(1)
	{
		while(i++<255){for(j=0;j<8;j++){color[j]=i<<16;}Ws2812Pixel((pixel_t *)color,len);osDelay(dly);}
		while(i-->  1){for(j=0;j<8;j++){color[j]=i<<16;}Ws2812Pixel((pixel_t *)color,len);osDelay(dly);}
		while(i++<255){for(j=0;j<8;j++){color[j]=i<< 8;}Ws2812Pixel((pixel_t *)color,len);osDelay(dly);}
		while(i-->  1){for(j=0;j<8;j++){color[j]=i<< 8;}Ws2812Pixel((pixel_t *)color,len);osDelay(dly);}
		while(i++<255){for(j=0;j<8;j++){color[j]=i<< 0;}Ws2812Pixel((pixel_t *)color,len);osDelay(dly);}
		while(i-->  1){for(j=0;j<8;j++){color[j]=i<< 0;}Ws2812Pixel((pixel_t *)color,len);osDelay(dly);}
	}
}

全文完毕。

#76 华芯微特 » 基于华芯微特SWM181CBT6的I2C的HTU21D温度湿度传感器驱动程序开发-缥缈九哥 » 2020-05-09 18:19:38

缥缈九哥
回复: 1

不废话,上代码:

/********************************************************************************
 * @file     htu20d.c															*
 * @brief    The Driver code for HTU21D with SWM181CBT6							*
 * @version  1.0.0																*
 * @date     2018/08/23  01:35:35												*
 *																				*
 * @note																		*
 * Copyright (C) 2000-2018 PM9GZY by yuanxihua@21cn.com. All rights reserved.	*
 ********************************************************************************/
/* Includes --------------------------------------------------------------------*/
#include "wall.h"
/*
_________________________________________________
|	SWM181CBT6						HTU20D		|
|												|
|	SDA -	PD3			<--->		SDA			|
|	SCL -	PD2			 --->		SCL			|
|_______________________________________________|
*/
/* Private typedef -----------------------------------------------------------*/
typedef enum {START=0x01,STOP=0x02,WRD=0x04,RDA=0x08,ACK=0x10,NAK=0x20}i2c_status_t;
typedef enum {TEMP=0xF3,HUMID=0xF5,TEMPHOLD=0xE3,HUMIDHOLD=0xE5,WRUSER=0xE6,RDUSER=0xE7,RESET=0xFE}i2c_cmd_t;
/* Private define ------------------------------------------------------------*/
#define HTU20D_I2C_CLK_HZ      		100000 			/* Clock i2c speed 100KHz */
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
void I2C0Init(void)
{
	I2C_InitStructure I2C_initStruct;
	
	PORT_Init(PORTD, PIN2, FUNMUX_I2C0_SCL, 1);		//GPIOD.2配置为I2C0 SCL引脚
	PORT_Init(PORTD, PIN3, FUNMUX_I2C0_SDA, 1);		//GPIOD.3配置为I2C0 SDA引脚
	PORTD->OPEND |= (1 << PIN2)|(1 << PIN3);		//开漏
	PORTD->PULLU |= (1 << PIN2)|(1 << PIN3);		//上拉

	I2C_initStruct.Master = 1;
	I2C_initStruct.Addr7b = 1;
	I2C_initStruct.MstClk = HTU20D_I2C_CLK_HZ;
	I2C_initStruct.MstIEn = 0;
	I2C_Init(I2C0, &I2C_initStruct);
	I2C_Open(I2C0);
	//After power up, the device needs at most 15ms while SCK is high
	osDelay(20); 
}
void I2C_SEND_STATUS(I2C_TypeDef *i2c,i2c_status_t status)	
{
	uint8_t cmd=0;
	if(status & START){cmd |=  (1 << I2C_MSTCMD_STA_Pos);}	 	//set start
	if(status & STOP ){cmd |=  (1 << I2C_MSTCMD_STO_Pos);}		//set stop 
	if(status & WRD  ){cmd |=  (1 << I2C_MSTCMD_WR_Pos );}		//set write
	if(status & RDA  ){cmd |=  (1 << I2C_MSTCMD_RD_Pos );}		//set read 
	if(status & ACK  ){cmd &= ~(0 << I2C_MSTCMD_ACK_Pos);}		//set ack 
	if(status & NAK  ){cmd |=  (1 << I2C_MSTCMD_ACK_Pos);}		//set nack 
	i2c->MSTCMD=cmd;while(i2c->MSTCMD & I2C_MSTCMD_TIP_Msk){;}	//等待发送完成
}	
uint8_t I2C_SEND_DATA(I2C_TypeDef *i2c,uint8_t data,i2c_status_t status)		
{
	i2c->MSTDAT=data;
	I2C_SEND_STATUS(i2c,status);
	return (i2c->MSTCMD & I2C_MSTCMD_RXACK_Msk)?NAK:ACK;
}
uint8_t I2C_READ_DATA(I2C_TypeDef *i2c,i2c_status_t status)		
{
	I2C_SEND_STATUS(i2c,status);
	return i2c->MSTDAT;
}
void HTU20D_Soft_Reset(void)
{
	uint8_t ack;ack=ack;
	//send i2c start + address + write
	ack=I2C_SEND_DATA(I2C0,0x80,START|WRD);
	//send Soft Reset Command
	ack=I2C_SEND_DATA(I2C0,RESET,WRD|STOP);//0xFE
	//The soft reset takes less than 15ms.
	osDelay(20); 
}
uint8_t HTU20D_Read_User_Register(void)
{
	uint8_t ack;ack=ack;
   	//send i2c start + address + write
	ack=I2C_SEND_DATA(I2C0,0x80,START|WRD);
	//send Read Register Command
	ack=I2C_SEND_DATA(I2C0,RDUSER,WRD);//0xE7
	//send i2c start + address + read
	ack=I2C_SEND_DATA(I2C0,0x81,START|WRD);
	//read Register content
	uint8_t data=I2C_READ_DATA(I2C0,RDA|NAK|STOP);
	//wait i2c delay
	osDelay(20);
	return data;
}
void HTU20D_Write_User_Register(uint8_t data)
{
	uint8_t ack;ack=ack;
   	//send i2c start + address + write
	ack=I2C_SEND_DATA(I2C0,0x80,START|WRD);
	//send Write Register Command
	ack=I2C_SEND_DATA(I2C0,WRUSER,WRD);//0xE6
	//send Register Content to be written
	ack=I2C_SEND_DATA(I2C0,data,WRD|STOP);
	//wait i2c delay
	osDelay(20);
}
uint16_t HTU20D_Read_Temperature_Humidity(i2c_cmd_t cmd)
{
	uint8_t ack;ack=ack;
   	//send i2c start + address + write
	ack=I2C_SEND_DATA(I2C0,0x80,START|WRD);
	//send Read Register Command
	ack=I2C_SEND_DATA(I2C0,cmd,WRD);
	//continue measuring
	while(I2C_SEND_DATA(I2C0,0x81,START|WRD)==NAK){;}
	//read Register content MSB
	uint16_t data =I2C_READ_DATA(I2C0,RDA|ACK);
	//read Register content LSB
	data=(data<<8)+I2C_READ_DATA(I2C0,RDA|ACK);	
	//read Checksum
	uint16_t cks = I2C_READ_DATA(I2C0,RDA|NAK|STOP);
	//wait i2c delay
	osDelay(20);
	return data;
}
void HTU20D_Read(float *Temperature, float *Humidity)
{
	float temp;
	temp=HTU20D_Read_Temperature_Humidity(TEMP )&0xfffc;
//	printf("HTU20D_Read Temperature=0x%x\n\r",(int)temp);
	*Temperature=((temp*175.72)/65536)-46.85;
	temp=HTU20D_Read_Temperature_Humidity(HUMID)&0xfffc;
//	printf("HTU20D_Read Humidity   =0x%x\n\r",(int)temp);
	*Humidity=((temp*125)/65536)-6;
}
void HTU20D_test(void)
{
	float Humidity,Temperature;
	HTU20D_Soft_Reset();
	HTU20D_Write_User_Register(0x00);
	printf("HTU20D User_Registe=0x%02x\n\r",HTU20D_Read_User_Register());
	
	HTU20D_Read(&Temperature,&Humidity);
	printf("HTU20D Trigger No Hold T=%f 摄氏度 H=%f %%RH\n\r",Temperature,Humidity);
}

//代码完毕

页脚

工信部备案:粤ICP备20025096号 Powered by FluxBB

感谢为中文互联网持续输出优质内容的各位老铁们。 QQ: 516333132, 微信(wechat): whycan_cn (哇酷网/挖坑网/填坑网) service@whycan.cn