I do this
all day long at work. I'm a consultant who both teaches programming to people as well as develops full products for them.
There are three keys to remember: These people aren't stupid because they are uninformed about the thing you know alot about. You will lose them very quickly if you go into jargon. You do not need to explain every intricacy, you can be more accurate in the large by being inaccurate in the small.
So for instance, someone wants to understand what goes on in an iPhone app. If they're completely non-technical, I often call programs things like "very talented guy with no common sense", "idiot savant", "well trained dog that knows a lot of tricks", etc. This is getting across by analogy the idea that the program will not figure out how to do ANYTHING on its own, by implying it only knows what to do what we put in it.
So then I tell them "the way apple makes all iphone apps, there is a place to put things we want to happen when the application starts running. What do you want to happen there?". Then I toss that in there, and then ask them all the other niggling details, explaining if we don't tell it what we want those details to be, it will be "whatever standard thing apple decided will happen", like just ordering a salad at a restaurant without specifying further.
Then I ask what you want to happen in this location in the program, and that location, then we go through exceptional conditions (for an iPhone app, that would be stuff like "No network available" etc).
When you do this for awhile, you often want to stop, otherwise you're not explaining programming, you're actually programming. But they get the picture.
Another analogy:
When programming you're basically telling a very stupid, very detailed, very dedicated person how to build a very ornate house from the ground up. In that analogy, the program is the "process of building the house". The house is analogous to what is made every time you run the application.